summaryrefslogtreecommitdiff
path: root/apps/codecs/libgme/hes_cpu.h
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/libgme/hes_cpu.h')
-rw-r--r--apps/codecs/libgme/hes_cpu.h119
1 files changed, 78 insertions, 41 deletions
diff --git a/apps/codecs/libgme/hes_cpu.h b/apps/codecs/libgme/hes_cpu.h
index 4d76c83a3b..0429eeaba0 100644
--- a/apps/codecs/libgme/hes_cpu.h
+++ b/apps/codecs/libgme/hes_cpu.h
@@ -1,56 +1,52 @@
1// PC Engine CPU emulator for use with HES music files 1// PC Engine CPU emulator for use with HES music files
2 2
3// Game_Music_Emu 0.5.2 3// Game_Music_Emu 0.6-pre
4#ifndef HES_CPU_H 4#ifndef HES_CPU_H
5#define HES_CPU_H 5#define HES_CPU_H
6 6
7#include "blargg_common.h" 7#include "blargg_common.h"
8#include "blargg_source.h"
8 9
9typedef blargg_long hes_time_t; // clock cycle count 10typedef int hes_time_t; // clock cycle count
10typedef unsigned hes_addr_t; // 16-bit address 11typedef int hes_addr_t; // 16-bit address
11 12
12struct Hes_Emu; 13struct Hes_Emu;
13 14
14enum { future_hes_time = LONG_MAX / 2 + 1 }; 15enum { future_time = INT_MAX/2 + 1 };
15enum { page_size = 0x2000 }; 16enum { page_bits = 13 };
16enum { page_shift = 13 }; 17enum { page_size = 1 << page_bits };
17enum { page_count = 8 }; 18enum { page_count = 0x10000 / page_size };
18 19
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)
22enum { idle_addr = 0x1FFF };
23
24// Can read this many bytes past end of a page 20// Can read this many bytes past end of a page
25enum { cpu_padding = 8 }; 21enum { cpu_padding = 8 };
26enum { irq_inhibit = 0x04 }; 22enum { irq_inhibit_mask = 0x04 };
27 23enum { idle_addr = 0x1FFF };
28 24
29// Cpu state 25// Cpu state
30struct state_t { 26struct cpu_state_t {
31 uint8_t const* code_map [page_count + 1]; 27 byte const* code_map [page_count + 1];
32 hes_time_t base; 28 hes_time_t base;
33 blargg_long time; 29 int time;
34}; 30};
35 31
36// Cpu registers 32// NOT kept updated during emulation.
37struct registers_t { 33struct registers_t {
38 uint16_t pc; 34 uint16_t pc;
39 uint8_t a; 35 byte a;
40 uint8_t x; 36 byte x;
41 uint8_t y; 37 byte y;
42 uint8_t status; 38 byte flags;
43 uint8_t sp; 39 byte sp;
44}; 40};
45 41
46struct Hes_Cpu { 42struct Hes_Cpu {
47 struct registers_t r; 43 struct registers_t r;
48 44
49 hes_time_t irq_time; 45 hes_time_t irq_time_;
50 hes_time_t end_time; 46 hes_time_t end_time_;
51 47
52 struct state_t* state; // points to state_ or a local copy within run() 48 struct cpu_state_t* cpu_state; // points to state_ or a local copy within run()
53 struct state_t state_; 49 struct cpu_state_t cpu_state_;
54 50
55 // page mapping registers 51 // page mapping registers
56 uint8_t mmr [page_count + 1]; 52 uint8_t mmr [page_count + 1];
@@ -58,7 +54,10 @@ struct Hes_Cpu {
58}; 54};
59 55
60// Init cpu state 56// Init cpu state
61void Cpu_init( struct Hes_Cpu* this ); 57static inline void Cpu_init( struct Hes_Cpu* this )
58{
59 this->cpu_state = &this->cpu_state_;
60}
62 61
63// Reset hes cpu 62// Reset hes cpu
64void Cpu_reset( struct Hes_Cpu* this ); 63void Cpu_reset( struct Hes_Cpu* this );
@@ -67,29 +66,67 @@ void Cpu_reset( struct Hes_Cpu* this );
67// instructions were encountered. 66// instructions were encountered.
68bool Cpu_run( struct Hes_Emu* this, hes_time_t end_time ); 67bool Cpu_run( struct Hes_Emu* this, hes_time_t end_time );
69 68
70void Cpu_set_mmr( struct Hes_Emu* this, int reg, int bank );
71
72// Time of ning of next instruction to be executed 69// Time of ning of next instruction to be executed
73static inline hes_time_t Cpu_time( struct Hes_Cpu* this ) 70static inline hes_time_t Cpu_time( struct Hes_Cpu* this )
74{ 71{
75 return this->state->time + this->state->base; 72 return this->cpu_state->time + this->cpu_state->base;
76} 73}
77 74
75static inline void Cpu_set_time( struct Hes_Cpu* this, hes_time_t t ) { this->cpu_state->time = t - this->cpu_state->base; }
76static inline void Cpu_adjust_time( struct Hes_Cpu* this, int delta ) { this->cpu_state->time += delta; }
77
78#define HES_CPU_PAGE( addr ) ((unsigned) (addr) >> page_bits)
79
80#ifdef BLARGG_NONPORTABLE
81 #define HES_CPU_OFFSET( addr ) (addr)
82#else
83 #define HES_CPU_OFFSET( addr ) ((addr) & (page_size - 1))
84#endif
85
78static inline uint8_t const* Cpu_get_code( struct Hes_Cpu* this, hes_addr_t addr ) 86static inline uint8_t const* Cpu_get_code( struct Hes_Cpu* this, hes_addr_t addr )
79{ 87{
80 return this->state->code_map [addr >> page_shift] + addr 88 return this->cpu_state_.code_map [HES_CPU_PAGE( addr )] + HES_CPU_OFFSET( addr );
81 #if !defined (BLARGG_NONPORTABLE) 89}
82 % (unsigned) page_size 90
83 #endif 91static inline void update_end_time( struct Hes_Cpu* this, hes_time_t end, hes_time_t irq )
84 ; 92{
93 if ( end > irq && !(this->r.flags & irq_inhibit_mask) )
94 end = irq;
95
96 this->cpu_state->time += this->cpu_state->base - end;
97 this->cpu_state->base = end;
98}
99
100static inline hes_time_t Cpu_end_time( struct Hes_Cpu* this ) { return this->end_time_; }
101
102static inline void Cpu_set_irq_time( struct Hes_Cpu* this, hes_time_t t )
103{
104 this->irq_time_ = t;
105 update_end_time( this, this->end_time_, t );
106}
107
108static inline void Cpu_set_end_time( struct Hes_Cpu* this, hes_time_t t )
109{
110 this->end_time_ = t;
111 update_end_time( this, t, this->irq_time_ );
112}
113
114static inline void Cpu_end_frame( struct Hes_Cpu* this, hes_time_t t )
115{
116 assert( this->cpu_state == &this->cpu_state_ );
117 this->cpu_state_.base -= t;
118 if ( this->irq_time_ < future_time ) this->irq_time_ -= t;
119 if ( this->end_time_ < future_time ) this->end_time_ -= t;
85} 120}
86 121
87static inline int Cpu_update_end_time( struct Hes_Cpu* this, uint8_t reg_status, hes_time_t t, hes_time_t irq ) 122static inline void Cpu_set_mmr( struct Hes_Cpu* this, int reg, int bank, void const* code )
88{ 123{
89 if ( irq < t && !(reg_status & irq_inhibit) ) t = irq; 124 assert( (unsigned) reg <= page_count ); // allow page past end to be set
90 int delta = this->state->base - t; 125 assert( (unsigned) bank < 0x100 );
91 this->state->base = t; 126 this->mmr [reg] = bank;
92 return delta; 127 byte const* p = STATIC_CAST(byte const*,code) - HES_CPU_OFFSET( reg << page_bits );
128 this->cpu_state->code_map [reg] = p;
129 this->cpu_state_.code_map [reg] = p;
93} 130}
94 131
95#endif 132#endif