diff options
Diffstat (limited to 'apps/codecs/libgme/hes_cpu.h')
-rw-r--r-- | apps/codecs/libgme/hes_cpu.h | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/apps/codecs/libgme/hes_cpu.h b/apps/codecs/libgme/hes_cpu.h new file mode 100644 index 0000000000..f3bcf7d4cf --- /dev/null +++ b/apps/codecs/libgme/hes_cpu.h | |||
@@ -0,0 +1,95 @@ | |||
1 | // PC Engine CPU emulator for use with HES music files | ||
2 | |||
3 | // Game_Music_Emu 0.5.2 | ||
4 | #ifndef HES_CPU_H | ||
5 | #define HES_CPU_H | ||
6 | |||
7 | #include "blargg_common.h" | ||
8 | |||
9 | typedef blargg_long hes_time_t; // clock cycle count | ||
10 | typedef unsigned hes_addr_t; // 16-bit address | ||
11 | |||
12 | struct Hes_Emu; | ||
13 | |||
14 | enum { future_hes_time = LONG_MAX / 2 + 1 }; | ||
15 | enum { page_size = 0x2000 }; | ||
16 | enum { page_shift = 13 }; | ||
17 | enum { page_count = 8 }; | ||
18 | |||
19 | // Attempt to execute instruction here results in CPU advancing time to | ||
20 | // lesser of irq_time() and end_time() (or end_time() if IRQs are | ||
21 | // disabled) | ||
22 | enum { idle_addr = 0x1FFF }; | ||
23 | |||
24 | // Can read this many bytes past end of a page | ||
25 | enum { cpu_padding = 8 }; | ||
26 | enum { irq_inhibit = 0x04 }; | ||
27 | |||
28 | |||
29 | // Cpu state | ||
30 | struct state_t { | ||
31 | uint8_t const* code_map [page_count + 1]; | ||
32 | hes_time_t base; | ||
33 | blargg_long time; | ||
34 | }; | ||
35 | |||
36 | // Cpu registers | ||
37 | struct registers_t { | ||
38 | uint16_t pc; | ||
39 | uint8_t a; | ||
40 | uint8_t x; | ||
41 | uint8_t y; | ||
42 | uint8_t status; | ||
43 | uint8_t sp; | ||
44 | }; | ||
45 | |||
46 | struct Hes_Cpu { | ||
47 | struct registers_t r; | ||
48 | |||
49 | hes_time_t irq_time; | ||
50 | hes_time_t end_time; | ||
51 | |||
52 | struct state_t* state; // points to state_ or a local copy within run() | ||
53 | struct state_t state_; | ||
54 | |||
55 | // page mapping registers | ||
56 | uint8_t mmr [page_count + 1]; | ||
57 | uint8_t ram [page_size]; | ||
58 | }; | ||
59 | |||
60 | // Init cpu state | ||
61 | void Cpu_init( struct Hes_Cpu* this ); | ||
62 | |||
63 | // Reset hes cpu | ||
64 | void Cpu_reset( struct Hes_Cpu* this ); | ||
65 | |||
66 | // Set end_time and run CPU from current time. Returns true if any illegal | ||
67 | // instructions were encountered. | ||
68 | bool Cpu_run( struct Hes_Emu* this, hes_time_t end_time ) ICODE_ATTR; | ||
69 | |||
70 | void Cpu_set_mmr( struct Hes_Emu* this, int reg, int bank ) ICODE_ATTR; | ||
71 | |||
72 | // Time of ning of next instruction to be executed | ||
73 | static inline hes_time_t Cpu_time( struct Hes_Cpu* this ) | ||
74 | { | ||
75 | return this->state->time + this->state->base; | ||
76 | } | ||
77 | |||
78 | static inline uint8_t const* Cpu_get_code( struct Hes_Cpu* this, hes_addr_t addr ) | ||
79 | { | ||
80 | return this->state->code_map [addr >> page_shift] + addr | ||
81 | #if !defined (BLARGG_NONPORTABLE) | ||
82 | % (unsigned) page_size | ||
83 | #endif | ||
84 | ; | ||
85 | } | ||
86 | |||
87 | static inline int Cpu_update_end_time( struct Hes_Cpu* this, uint8_t reg_status, hes_time_t t, hes_time_t irq ) | ||
88 | { | ||
89 | if ( irq < t && !(reg_status & irq_inhibit) ) t = irq; | ||
90 | int delta = this->state->base - t; | ||
91 | this->state->base = t; | ||
92 | return delta; | ||
93 | } | ||
94 | |||
95 | #endif | ||