Implement vertical refresh interrupt and tile generator, Pac-Man can now run
authorNick Downing <nick@ndcode.org>
Sat, 2 Jul 2022 01:49:48 +0000 (11:49 +1000)
committerNick Downing <nick@ndcode.org>
Sat, 2 Jul 2022 01:49:48 +0000 (11:49 +1000)
emu_z80/emu_z80.c
emu_z80/test.asm

index ef11105..d9596f9 100644 (file)
 #define SAMPLES_PER_UPDATE 500
 
 #if PACMAN
-// define pacman I/O addresses here
+#define INT_VECTOR 0
+
+#define TILE_RAM 0x4000
+#define PALETTE_RAM 0x4400
 #else // APPLE
 #define IO_PAGE 0xe000
 #define HW_KBD 0xe000 // R last key pressed + 128
 #endif
 
 #define TRACE 0
-#define IO_TRACE 1
-#define MEM_TRACE 1
+#define IO_TRACE 0
+#define MEM_TRACE 0
 
 extern char **environ;
 
@@ -154,6 +157,25 @@ uint32_t frame[WINDOW_HEIGHT][WINDOW_WIDTH];
 
 // see palette.py
 uint32_t palette[0x10] = {
+#if PACMAN
+  // see https://www.lomont.org/software/games/pacman/PacmanEmulation.pdf
+  0xff000000,
+  0xffff0000,
+  0xffde9751,
+  0xffffb8ff,
+  0xff000000,
+  0xff00ffff,
+  0xff47b8ff,
+  0xffffb851,
+  0xff000000,
+  0xffffff00,
+  0xff000000,
+  0xff2121ff,
+  0xff00ff00,
+  0xff47b8ae,
+  0xffffb8ae,
+  0xffdedeff,
+#else // APPLE
   0xff000000,
   0xffbc0089,
   0xff0000bc,
@@ -170,6 +192,7 @@ uint32_t palette[0x10] = {
   0xffffffbc,
   0xffbcffe1,
   0xffffffff,
+#endif
 };
 
 // can make this green or amber to be more realistic
@@ -243,7 +266,7 @@ uint8_t dos_lo;
 int usleep_count, exit_flag;
 
 #if PACMAN
-// define pacman I/O state here
+uint8_t int_vector;
 
 // just for now until we have pacman audio
 #define C0X0_SOFT_SWITCH_TAPEOUT 4
@@ -1238,6 +1261,11 @@ void out(z80 *const z, uint8_t port, uint8_t val) {
 #endif
 
   switch (port) {
+#if PACMAN
+  case INT_VECTOR:
+    int_vector = val;
+    break;
+#endif
   case STDOUT_DATA:
     if (write(fd_out, &val, 1) == -1) {
       perror("write()");
@@ -1565,6 +1593,10 @@ int main(int argc, char **argv) {
     fd_out = fd_master;
   }
 
+// not sure why this was needed
+// keyboard input should be via SDL2
+// HRCG input should be via a pty master (not slave)
+#if 0
   if (isatty(fd_in)) {
     if (tcgetattr(fd_in, &termios_attr) == -1) {
       perror("tcgetattr()");
@@ -1595,6 +1627,7 @@ int main(int argc, char **argv) {
       exit(EXIT_FAILURE);
     }
   }
+#endif
 
   if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) {
     fprintf(stderr, "SDL_Init(): %s\n\n", SDL_GetError());
@@ -1864,7 +1897,38 @@ int main(int argc, char **argv) {
       SDL_RenderClear(renderer);
 
 #if PACMAN
-      // define pacman video update here
+      // send z80 a vertical refresh interrupt
+      cpu.int_pending = true;
+      cpu.int_data = int_vector;
+
+      for (int i = 0; i < 36; ++i)
+        for (int j = 0; j < 28; ++j) {
+          int offset =
+            i < 2 ?
+              0x3dd + (i << 5) - j :
+              i < 34 ?
+                0x3a0 - 2 + i - (j << 5) :
+                0x1d - (34 << 5) + (i << 5) - j;
+          int tile_base =
+            ROM_PACMAN_5E_ADDR | (mem[TILE_RAM | offset] << 4) | 0xf;
+          int palette_base =
+            ROM_82S126_4A_ADDR | ((mem[PALETTE_RAM | offset] & 0x3f) << 2);
+          for (int k = 0; k < 8; ++k) {
+            int y = ((i << 3) | k) * WINDOW_Y_SCALE;
+            for (int l = 0; l < 8; ++l) {
+              int data = mem[tile_base ^ ((k & 4) << 1) ^ l] << (k & 3);
+              uint32_t rgb = palette[
+                mem[
+                  palette_base | ((data & 8) >> 3) | ((data & 0x80) >> 6)
+                ] & 0xf
+              ];
+              int x = ((j << 3) | l) * WINDOW_X_SCALE;
+              for (int m = 0; m < WINDOW_Y_SCALE; ++m)
+                for (int n = 0; n < WINDOW_X_SCALE; ++n)
+                  frame[y + m][x + n] = rgb;
+            }
+          }
+        } 
 #else // APPLE
       struct timespec timeval;
       clock_gettime(CLOCK_MONOTONIC, &timeval);
index 410dc42..e11c8c0 100644 (file)
@@ -1,3 +1,6 @@
+PACMAN = 1
+APPLE = 0
+
 STDIN_DATA = 0xf0
 STDOUT_DATA = 0xf1
 STDERR_DATA = 0xf2
@@ -8,6 +11,10 @@ USLEEP_LO = 0xf6
 USLEEP_HI = 0xf7
 SYS_EXIT = 0xf8
 
+.if PACMAN
+TILE_RAM = 0x4000
+PALETTE_RAM = 0x4400
+.else ; APPLE
 ; read
 HW_KBD = 0xe000
 
@@ -30,9 +37,16 @@ HW_SETHIRES = 0xe057
 HW_SETDHIRES = 0xe05e
 HW_SETIOUDIS = 0xe07e
 HW_CLRIOUDIS = 0xe07f
+.endif
 
        .area   text
 
+.if PACMAN
+       sub     a
+       ld      (TILE_RAM | 0x3dd),a
+       inc     a
+       ld      (PALETTE_RAM | 0x3dd),a
+.else ; APPLE
        ld      (HW_CLR80COL),a
        ld      a,(HW_CLRIOUDIS)
 
@@ -42,6 +56,7 @@ HW_CLRIOUDIS = 0xe07f
        ld      a,(HW_CLRMIXED)
        ld      a,(HW_PAGE1)
        ld      (HW_SET80VID),a
+.endif
 
        ld      hl,message
        ld      b,message_end - message