diff options
Diffstat (limited to 'apps/codecs/libgme/nes_cpu.h')
-rw-r--r-- | apps/codecs/libgme/nes_cpu.h | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/apps/codecs/libgme/nes_cpu.h b/apps/codecs/libgme/nes_cpu.h new file mode 100644 index 0000000000..7129ffd925 --- /dev/null +++ b/apps/codecs/libgme/nes_cpu.h | |||
@@ -0,0 +1,106 @@ | |||
1 | // NES cpu emulator | ||
2 | |||
3 | // Game_Music_Emu 0.6-pre | ||
4 | #ifndef NES_CPU_H | ||
5 | #define NES_CPU_H | ||
6 | |||
7 | #include "blargg_common.h" | ||
8 | #include "blargg_source.h" | ||
9 | |||
10 | typedef int nes_time_t; | ||
11 | typedef int addr_t; | ||
12 | |||
13 | enum { page_bits = 11 }; | ||
14 | enum { page_size = 1 << page_bits }; | ||
15 | enum { page_count = 0x10000 >> page_bits }; | ||
16 | |||
17 | // Unmapped page should be filled with this | ||
18 | enum { halt_opcode = 0x22 }; | ||
19 | |||
20 | enum { future_time = INT_MAX/2 + 1 }; | ||
21 | enum { irq_inhibit_mask = 0x04 }; | ||
22 | |||
23 | // Can read this many bytes past end of a page | ||
24 | enum { cpu_padding = 8 }; | ||
25 | |||
26 | struct registers_t { | ||
27 | uint16_t pc; | ||
28 | uint8_t a; | ||
29 | uint8_t x; | ||
30 | uint8_t y; | ||
31 | uint8_t flags; | ||
32 | uint8_t sp; | ||
33 | }; | ||
34 | |||
35 | struct cpu_state_t { | ||
36 | uint8_t const* code_map [page_count + 1]; | ||
37 | nes_time_t base; | ||
38 | int time; | ||
39 | }; | ||
40 | |||
41 | struct Nes_Cpu { | ||
42 | // NES 6502 registers. NOT kept updated during emulation. | ||
43 | struct registers_t r; | ||
44 | nes_time_t irq_time; | ||
45 | nes_time_t end_time; | ||
46 | |||
47 | struct cpu_state_t* cpu_state; // points to cpu_state_ or a local copy | ||
48 | struct cpu_state_t cpu_state_; | ||
49 | }; | ||
50 | |||
51 | static inline void Cpu_init( struct Nes_Cpu* this ) { this->cpu_state = &this->cpu_state_; } | ||
52 | |||
53 | // Clears registers and maps all pages to unmapped_page | ||
54 | void Cpu_reset( struct Nes_Cpu* this, void const* unmapped_page ); | ||
55 | |||
56 | // Maps code memory (memory accessed via the program counter). Start and size | ||
57 | // must be multiple of page_size. If mirror_size is non-zero, the first | ||
58 | // mirror_size bytes are repeated over the range. mirror_size must be a | ||
59 | // multiple of page_size. | ||
60 | void Cpu_map_code( struct Nes_Cpu* this, addr_t start, int size, void const* code, int mirror_size ); | ||
61 | |||
62 | // Time of beginning of next instruction to be executed | ||
63 | static inline nes_time_t Cpu_time( struct Nes_Cpu* this ) { return this->cpu_state->time + this->cpu_state->base; } | ||
64 | static inline void Cpu_set_time( struct Nes_Cpu* this, nes_time_t t ) { this->cpu_state->time = t - this->cpu_state->base; } | ||
65 | static inline void Cpu_adjust_time( struct Nes_Cpu* this, int delta ) { this->cpu_state->time += delta; } | ||
66 | |||
67 | // Clocks past end (negative if before) | ||
68 | static inline int Cpu_time_past_end( struct Nes_Cpu* this ) { return this->cpu_state->time; } | ||
69 | |||
70 | #define NES_CPU_PAGE( addr ) ((unsigned) (addr) >> page_bits) | ||
71 | |||
72 | #ifdef BLARGG_NONPORTABLE | ||
73 | #define NES_CPU_OFFSET( addr ) (addr) | ||
74 | #else | ||
75 | #define NES_CPU_OFFSET( addr ) ((addr) & (page_size - 1)) | ||
76 | #endif | ||
77 | |||
78 | // Accesses emulated memory as cpu does | ||
79 | static inline uint8_t const* Cpu_get_code( struct Nes_Cpu* this, addr_t addr ) | ||
80 | { | ||
81 | return this->cpu_state_.code_map [NES_CPU_PAGE( addr )] + NES_CPU_OFFSET( addr ); | ||
82 | } | ||
83 | |||
84 | static inline void Cpu_update_end_time( struct Nes_Cpu* this, nes_time_t end, nes_time_t irq ) | ||
85 | { | ||
86 | if ( end > irq && !(this->r.flags & irq_inhibit_mask) ) | ||
87 | end = irq; | ||
88 | |||
89 | this->cpu_state->time += this->cpu_state->base - end; | ||
90 | this->cpu_state->base = end; | ||
91 | } | ||
92 | |||
93 | // Time of next IRQ | ||
94 | static inline void Cpu_set_irq_time( struct Nes_Cpu* this, nes_time_t t ) | ||
95 | { | ||
96 | this->irq_time = t; | ||
97 | Cpu_update_end_time( this, this->end_time, t ); | ||
98 | } | ||
99 | |||
100 | static inline void Cpu_set_end_time( struct Nes_Cpu* this, nes_time_t t ) | ||
101 | { | ||
102 | this->end_time = t; | ||
103 | Cpu_update_end_time( this, t, this->irq_time ); | ||
104 | } | ||
105 | |||
106 | #endif | ||