Turn VBL break point list into a structure to make game stop at various events
authorAndreas Eversberg <jolly@eversberg.eu>
Sun, 4 Mar 2018 17:23:03 +0000 (18:23 +0100)
committerAndreas Eversberg <jolly@eversberg.eu>
Wed, 7 Mar 2018 17:22:54 +0000 (18:22 +0100)
Not only make the CPU execution stop when the game needs to wait for VBL.
But also other events, used to improve the game, like replacing rendering
routines by OpenGL.

src/libcpu/execute.c
src/libcpu/execute.h
src/mercenary/main.c
src/mercenary/mercenary.h
src/mercenary/mercenary2.c
src/mercenary/mercenary3.c

index fdbe8fc..d7421f3 100644 (file)
@@ -135,7 +135,7 @@ void reset_cpu(void)
        m68k_pulse_reset();
 }
 
-int execute_cpu(int irq, const uint32_t stop_at[])
+int execute_cpu(int irq, const struct cpu_stop stop_at[], int *event)
 {
        int cycle_count = 0;
        int instruction_count = 0;
@@ -169,16 +169,16 @@ int execute_cpu(int irq, const uint32_t stop_at[])
                                        break;
                        }
 
-                       for (i = 0; stop_at[i]; i++) {
-                               if (REG_PC == stop_at[i])
-                                       break;
-                       }
-                       if (stop_at[i])
-                               break;
-               } while (42);
+                       for (i = 0; stop_at[i].event; i++) {
+                               if (REG_PC == stop_at[i].pc) {
 #ifdef DEBUG_CPU
-               printf("execution to address 0x%06x took %d opcodes\n", REG_PC, instruction_count);
+                                       printf("execution to address 0x%06x took %d opcodes\n", REG_PC, instruction_count);
 #endif
+                                       *event = stop_at[i].event;
+                                       return cycle_count;
+                               }
+                       }
+               } while (42);
        }
 
        return cycle_count;
index e530829..64ef160 100644 (file)
@@ -1,7 +1,12 @@
 
+struct cpu_stop {
+       uint32_t        pc;
+       int             event;
+};
+
 void execute_init(int32_t _memory_size, uint8_t *_memory, uint16_t *_chipreg);
 void reset_cpu(void);
-int execute_cpu(int irq, const uint32_t stop_at[]);
+int execute_cpu(int irq, const struct cpu_stop stop_at[], int *event);
 uint16_t emulate_io_read(uint32_t address);
 void emulate_io_write(uint32_t address, uint16_t value);
 
index 10d002a..6e1af1c 100644 (file)
@@ -143,13 +143,17 @@ illegal_parameter:
        return 0;
 }
 
+static void special_event(int event)
+{
+}
+
 static void main_loop(void)
 {
        int had_first_irq = 0;
        static uint32_t current_time, last_time = 0, diff;
        int i, rc;
        int space, length;
-       int cycle_count;
+       int cycle_count, event;
        double render_delay = 0.0;
        uint32_t palette_address;
        uint16_t palette[16];
@@ -161,8 +165,14 @@ static void main_loop(void)
                /* STEP 1: let the CPU render/process the game */
                /* don't render if we still delay */
                if (!render_delay) {
-                       /* execute until the rendered image is ready */
-                       cycle_count = execute_cpu(0, mercenary_stop_at);
+                       /* execute until the rendered image is ready (wait for VBL) */
+                       cycle_count = 0;
+                       do {
+                               cycle_count += execute_cpu(0, mercenary_stop_at, &event);
+                               /* handle special events */
+                               if (event != STOP_AT_WAIT_VBL)
+                                       special_event(event);
+                       } while (event != STOP_AT_WAIT_VBL);
                        /* copy palette */
                        palette_address = mercenary_palette();
                        for (i = 0; i < 16; i++)
@@ -194,8 +204,8 @@ static void main_loop(void)
                        last_time = current_time - 1000 * SOUND_CHUNKS / IRQ_RATE;
                }
                while (diff > 1000 / IRQ_RATE) {
-                       execute_cpu(3, NULL);
-                       execute_cpu(4, NULL);
+                       execute_cpu(3, NULL, NULL);
+                       execute_cpu(4, NULL, NULL);
                        had_first_irq = 1;
                        /* render benson without game view
                         * because we only got benson refreshed during VBL IRQ
index c846f32..c89337d 100644 (file)
@@ -1,5 +1,8 @@
 
-extern const uint32_t mercenary_stop_at[];
+#define        STOP_AT_END             0
+#define STOP_AT_WAIT_VBL       1
+
+extern const struct cpu_stop mercenary_stop_at[];
 void mercenary_load(void);
 void mercenary_patch(void);
 uint32_t mercenary_palette(void);
index b8bad6c..4fd5df7 100644 (file)
 #include <stdint.h>
 #include <stdlib.h>
 #include "../libcpu/m68k.h"
+#include "../libcpu/execute.h"
 #include "mercenary.h"
 
 #define        INITIAL_STACK   0x7fffa
 #define RESET_VECTOR   0x59484
-const uint32_t mercenary_stop_at[] = {
-       0x59a4e,        /* done with rendering, waiting for VBL */
-       0x54c26,        /* after pressing 'HELP' key before showing menu line on benson */
-       0x55438,        /* waiting for menu command */
-       0x54c2e,        /* after pressing 'HELP' key while showing menu line on benson */
-       0x55446,        /* after pressing 'RETURN' while game waits for other key to resume */
-       0x51620,        /* after dying, waiting for VBL to fade out palette */
-       0x0 /* end */
-}; /* break points for rendering and continue with processing loop */
+
+/* interrupt CPU execution at special break points and tell emulation what to do */
+const struct cpu_stop mercenary_stop_at[] = {
+       { 0x59a4e,      STOP_AT_WAIT_VBL },     /* done with rendering, waiting for VBL */
+       { 0x54c26,      STOP_AT_WAIT_VBL },     /* after pressing 'HELP' key before showing menu line on benson */
+       { 0x55438,      STOP_AT_WAIT_VBL },     /* waiting for menu command */
+       { 0x54c2e,      STOP_AT_WAIT_VBL },     /* after pressing 'HELP' key while showing menu line on benson */
+       { 0x55446,      STOP_AT_WAIT_VBL },     /* after pressing 'RETURN' while game waits for other key to resume */
+       { 0x51620,      STOP_AT_WAIT_VBL },     /* after dying, waiting for VBL to fade out palette */
+       { 0x0,          STOP_AT_END },          /* end */
+};
 
 extern const uint32_t mercenary2_hex[];
 extern int mercenary2_hex_size;
index ba9cba1..163b312 100644 (file)
 #include <stdint.h>
 #include <stdlib.h>
 #include "../libcpu/m68k.h"
+#include "../libcpu/execute.h"
 #include "mercenary.h"
 
 #define        INITIAL_STACK   0x7fffa
 #define RESET_VECTOR   0x5a16c
 // #define RESET_VECTOR        0x5a1a4 /* strange reset vector that causes the player to fly around */
-const uint32_t mercenary_stop_at[] = {
-       0x5a826,        /* done with rendering, waiting for VBL */
-       0x55d8c,        /* after pressing 'HELP' key before showing menu line on benson */
-       0x56398,        /* waiting for menu command */
-       0x55d94,        /* after pressing 'HELP' key while showing menu line on benson */
-       0x563a6,        /* after pressing 'RETURN' while game waits for other key to resume */
-       0x52946,        /* after dying, waiting for VBL to fade out palette */
-       0x0 /* end */
-}; /* break points for rendering and continue with processing loop */
+
+/* interrupt CPU execution at special break points and tell emulation what to do */
+const struct cpu_stop mercenary_stop_at[] = {
+       { 0x5a826,      STOP_AT_WAIT_VBL },     /* done with rendering, waiting for VBL */
+       { 0x55d8c,      STOP_AT_WAIT_VBL },     /* after pressing 'HELP' key before showing menu line on benson */
+       { 0x56398,      STOP_AT_WAIT_VBL },     /* waiting for menu command */
+       { 0x55d94,      STOP_AT_WAIT_VBL },     /* after pressing 'HELP' key while showing menu line on benson */
+       { 0x563a6,      STOP_AT_WAIT_VBL },     /* after pressing 'RETURN' while game waits for other key to resume */
+       { 0x52946,      STOP_AT_WAIT_VBL },     /* after dying, waiting for VBL to fade out palette */
+       { 0x0,          STOP_AT_END },          /* end */
+};
 
 extern const uint32_t mercenary3_hex[];
 extern int mercenary3_hex_size;