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.
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;
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;
+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);
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];
/* 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++)
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
-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);
#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;
#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;