Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/quicknes/nes_emu/Nes_Mapper.h
2 views
1
2
// NES mapper interface
3
4
// Nes_Emu 0.7.0
5
6
#ifndef NES_MAPPER
7
#define NES_MAPPER
8
9
#include "Nes_Cart.h"
10
#include "Nes_Cpu.h"
11
#include "nes_data.h"
12
#include "Nes_Core.h"
13
class Blip_Buffer;
14
class blip_eq_t;
15
class Nes_Core;
16
17
class Nes_Mapper {
18
public:
19
// Register function that creates mapper for given code.
20
typedef Nes_Mapper* (*creator_func_t)();
21
static void register_mapper( int code, creator_func_t );
22
23
// Register optional mappers included with Nes_Emu
24
void register_optional_mappers();
25
26
// Create mapper appropriate for cartridge. Returns NULL if it uses unsupported mapper.
27
static Nes_Mapper* create( Nes_Cart const*, Nes_Core* );
28
29
virtual ~Nes_Mapper();
30
31
// Reset mapper to power-up state.
32
virtual void reset();
33
34
// Save snapshot of mapper state. Default saves registered state.
35
virtual void save_state( mapper_state_t& );
36
37
// Resets mapper, loads state, then applies it
38
virtual void load_state( mapper_state_t const& );
39
40
// I/O
41
42
// Read from memory
43
virtual int read( nes_time_t, nes_addr_t );
44
45
// Write to memory
46
virtual void write( nes_time_t, nes_addr_t, int data ) = 0;
47
48
// Write to memory below 0x8000 (returns false if mapper didn't handle write)
49
virtual bool write_intercepted( nes_time_t, nes_addr_t, int data );
50
51
// Timing
52
53
// Time returned when current mapper state won't ever cause an IRQ
54
enum { no_irq = LONG_MAX / 2 };
55
56
// Time next IRQ will occur at
57
virtual nes_time_t next_irq( nes_time_t present );
58
59
// Run mapper until given time
60
virtual void run_until( nes_time_t );
61
62
// End video frame of given length
63
virtual void end_frame( nes_time_t length );
64
65
// Sound
66
67
// Number of sound channels
68
virtual int channel_count() const;
69
70
// Set sound buffer for channel to output to, or NULL to silence channel.
71
virtual void set_channel_buf( int index, Blip_Buffer* );
72
73
// Set treble equalization
74
virtual void set_treble( blip_eq_t const& );
75
76
// Misc
77
78
// Called when bit 12 of PPU's VRAM address changes from 0 to 1 due to
79
// $2006 and $2007 accesses (but not due to PPU scanline rendering).
80
virtual void a12_clocked();
81
82
protected:
83
// Services provided for derived mapper classes
84
Nes_Mapper();
85
86
// Register state data to automatically save and load. Be sure the binary
87
// layout is suitable for use in a file, including any byte-order issues.
88
// Automatically cleared to zero by default reset().
89
void register_state( void*, unsigned );
90
91
// Enable 8K of RAM at 0x6000-0x7FFF, optionally read-only.
92
void enable_sram( bool enabled = true, bool read_only = false );
93
94
// Cause CPU writes within given address range to call mapper's write() function.
95
// Might map a larger address range, which the mapper can ignore and pass to
96
// Nes_Mapper::write(). The range 0x8000-0xffff is always intercepted by the mapper.
97
void intercept_writes( nes_addr_t addr, unsigned size );
98
99
// Cause CPU reads within given address range to call mapper's read() function.
100
// Might map a larger address range, which the mapper can ignore and pass to
101
// Nes_Mapper::read(). CPU opcode/operand reads and low-memory reads always
102
// go directly to memory and cannot be intercepted.
103
void intercept_reads( nes_addr_t addr, unsigned size );
104
105
// Bank sizes for mapping
106
enum bank_size_t { // 1 << bank_Xk = X * 1024
107
bank_1k = 10,
108
bank_2k = 11,
109
bank_4k = 12,
110
bank_8k = 13,
111
bank_16k = 14,
112
bank_32k = 15
113
};
114
115
// Index of last PRG/CHR bank. Last_bank selects last bank, last_bank - 1
116
// selects next-to-last bank, etc.
117
enum { last_bank = -1 };
118
119
// Map 'size' bytes from 'PRG + bank * size' to CPU address space starting at 'addr'
120
void set_prg_bank( nes_addr_t addr, bank_size_t size, int bank );
121
122
// Map 'size' bytes from 'CHR + bank * size' to PPU address space starting at 'addr'
123
void set_chr_bank( nes_addr_t addr, bank_size_t size, int bank );
124
void set_chr_bank_ex( nes_addr_t addr, bank_size_t size, int bank ); // mmc24 only
125
126
// Set PPU mirroring. All mappings implemented using mirror_manual().
127
void mirror_manual( int page0, int page1, int page2, int page3 );
128
void mirror_single( int page );
129
void mirror_horiz( int page = 0 );
130
void mirror_vert( int page = 0 );
131
void mirror_full();
132
133
// True if PPU rendering is enabled. Some mappers watch PPU memory accesses to determine
134
// when scanlines occur, and can only do this when rendering is enabled.
135
bool ppu_enabled() const;
136
137
// Cartridge being emulated
138
Nes_Cart const& cart() const { return *cart_; }
139
140
// Must be called when next_irq()'s return value is earlier than previous,
141
// current CPU run can be stopped earlier. Best to call whenever time may
142
// have changed (no performance impact if called even when time didn't change).
143
void irq_changed();
144
145
// Handle data written to mapper that doesn't handle bus conflict arising due to
146
// PRG also reading data. Returns data that mapper should act as if were
147
// written. Currently always returns 'data' and just checks that data written is
148
// the same as byte in PRG at same address and writes debug message if it doesn't.
149
int handle_bus_conflict( nes_addr_t addr, int data );
150
151
// Reference to emulator that uses this mapper.
152
Nes_Core& emu() const { return *emu_; }
153
154
protected:
155
// Services derived classes provide
156
157
// Read state from snapshot. Default reads data into registered state, then calls
158
// apply_mapping().
159
virtual void read_state( mapper_state_t const& );
160
161
// Apply current mapping state to hardware. Called after reading mapper state
162
// from a snapshot.
163
virtual void apply_mapping() = 0;
164
165
// Called by default reset() before apply_mapping() is called.
166
virtual void reset_state() { }
167
168
// End of general interface
169
private:
170
Nes_Core* emu_;
171
void* state;
172
unsigned state_size;
173
Nes_Cart const* cart_;
174
175
void default_reset_state();
176
177
struct mapping_t {
178
int code;
179
Nes_Mapper::creator_func_t func;
180
};
181
static mapping_t mappers [];
182
static creator_func_t get_mapper_creator( int code );
183
184
// built-in mappers
185
static Nes_Mapper* make_nrom();
186
static Nes_Mapper* make_unrom();
187
static Nes_Mapper* make_aorom();
188
static Nes_Mapper* make_cnrom();
189
static Nes_Mapper* make_mmc1();
190
static Nes_Mapper* make_mmc3();
191
};
192
193
template<class T>
194
struct register_mapper {
195
/*void*/ register_mapper( int code ) { Nes_Mapper::register_mapper( code, create ); }
196
static Nes_Mapper* create() { return BLARGG_NEW T; }
197
};
198
199
#ifdef NDEBUG
200
inline int Nes_Mapper::handle_bus_conflict( nes_addr_t addr, int data ) { return data; }
201
#endif
202
203
inline void Nes_Mapper::mirror_horiz( int p ) { mirror_manual( p, p, p ^ 1, p ^ 1 ); }
204
inline void Nes_Mapper::mirror_vert( int p ) { mirror_manual( p, p ^ 1, p, p ^ 1 ); }
205
inline void Nes_Mapper::mirror_single( int p ) { mirror_manual( p, p, p, p ); }
206
inline void Nes_Mapper::mirror_full() { mirror_manual( 0, 1, 2, 3 ); }
207
208
inline void Nes_Mapper::register_state( void* p, unsigned s )
209
{
210
assert( s <= max_mapper_state_size );
211
state = p;
212
state_size = s;
213
}
214
215
inline bool Nes_Mapper::write_intercepted( nes_time_t, nes_addr_t, int ) { return false; }
216
217
inline int Nes_Mapper::read( nes_time_t, nes_addr_t ) { return -1; } // signal to caller
218
219
inline void Nes_Mapper::intercept_reads( nes_addr_t addr, unsigned size )
220
{
221
emu().add_mapper_intercept( addr, size, true, false );
222
}
223
224
inline void Nes_Mapper::intercept_writes( nes_addr_t addr, unsigned size )
225
{
226
emu().add_mapper_intercept( addr, size, false, true );
227
}
228
229
inline void Nes_Mapper::enable_sram( bool enabled, bool read_only )
230
{
231
emu_->enable_sram( enabled, read_only );
232
}
233
234
#endif
235
236
237