Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/quicknes/nes_emu/Nes_Emu.h
2 views
1
2
// NES video game console emulator with snapshot support
3
4
// Nes_Emu 0.7.0
5
6
#ifndef NES_EMU_H
7
#define NES_EMU_H
8
9
#include "blargg_common.h"
10
#include "Multi_Buffer.h"
11
#include "Nes_Cart.h"
12
#include "Nes_Core.h"
13
class Nes_State;
14
15
// Register optional mappers included with Nes_Emu
16
void register_optional_mappers();
17
18
extern const char unsupported_mapper []; // returned when cartridge uses unsupported mapper
19
20
class Nes_Emu {
21
public:
22
Nes_Emu();
23
virtual ~Nes_Emu();
24
25
// Basic setup
26
27
// Load iNES file into emulator and clear recording
28
blargg_err_t load_ines( Auto_File_Reader );
29
30
// Set sample rate for sound generation
31
blargg_err_t set_sample_rate( long );
32
33
// Size and depth of graphics buffer required for rendering. Note that this
34
// is larger than the actual image, with a temporary area around the edge
35
// that gets filled with junk. Its height is many times larger in Nes_Recorder
36
// to allow caching of multiple images.
37
enum { buffer_width = Nes_Ppu::buffer_width };
38
int buffer_height() const { return buffer_height_; }
39
enum { bits_per_pixel = 8 };
40
41
private:
42
// Set graphics buffer to render pixels to. Pixels points to top-left pixel and
43
// row_bytes is the number of bytes to get to the next line (positive or negative).
44
void set_pixels( void* pixels, long row_bytes );
45
public:
46
47
// Size of image generated in graphics buffer
48
enum { image_width = 256 };
49
enum { image_height = 240 };
50
51
// Basic emulation
52
53
// Emulate one video frame using joypad1 and joypad2 as input. Afterwards, image
54
// and sound are available for output using the accessors below.
55
// A connected controller should have 0xffffff** in the high bits, or 0x000000**
56
// if emulating an incorrectly made third party controller. A disconnected controller
57
// should be 0x00000000 exactly.
58
virtual blargg_err_t emulate_frame( uint32_t joypad1, uint32_t joypad2 );
59
60
// Maximum size of palette that can be generated
61
enum { max_palette_size = 256 };
62
63
// Result of current frame
64
struct frame_t
65
{
66
int joypad_read_count; // number of times joypads were strobed (read)
67
int burst_phase; // NTSC burst phase for frame (0, 1, or 2)
68
69
int sample_count; // number of samples (always a multiple of chan_count)
70
int chan_count; // 1: mono, 2: stereo
71
72
int top; // top-left position of image in graphics buffer
73
enum { left = 8 };
74
unsigned char* pixels; // pointer to top-left pixel of image
75
long pitch; // number of bytes to get to next row of image
76
77
int palette_begin; // first host palette entry, as set by set_palette_range()
78
int palette_size; // number of entries used for current frame
79
short palette [max_palette_size]; // [palette_begin to palette_begin+palette_size-1]
80
};
81
frame_t const& frame() const { return *frame_; }
82
83
// Read samples for the current frame. Returns number of samples read into buffer.
84
// Currently all samples must be read in one call.
85
virtual long read_samples( short* out, long max_samples );
86
87
// Additional features
88
89
// Use already-loaded cartridge. Retains pointer, so it must be kept around until
90
// closed. A cartridge can be shared among multiple emulators. After opening,
91
// cartridge's CHR data shouldn't be modified since a copy is cached internally.
92
blargg_err_t set_cart( Nes_Cart const* );
93
94
// Pointer to current cartridge, or NULL if none is loaded
95
Nes_Cart const* cart() const { return emu.cart; }
96
97
// Free any memory and close cartridge, if one was currently open. A new cartridge
98
// must be opened before further emulation can take place.
99
void close();
100
101
// Emulate powering NES off and then back on. If full_reset is false, emulates
102
// pressing the reset button only, which doesn't affect memory, otherwise
103
// emulates powering system off then on.
104
virtual void reset( bool full_reset = true, bool erase_battery_ram = false );
105
106
// Number of undefined CPU instructions encountered. Cleared after reset() and
107
// load_state(). A non-zero value indicates that cartridge is probably
108
// incompatible.
109
unsigned long error_count() const { return emu.error_count; }
110
111
// Sound
112
113
// Set sample rate and use a custom sound buffer instead of the default
114
// mono buffer, i.e. Nes_Buffer, Effects_Buffer, etc..
115
blargg_err_t set_sample_rate( long rate, Multi_Buffer* );
116
117
// Adjust effective frame rate by changing how many samples are generated each frame.
118
// Allows fine tuning of frame rate to improve synchronization.
119
void set_frame_rate( double rate );
120
121
// Number of sound channels for current cartridge
122
int channel_count() const { return channel_count_; }
123
124
// Frequency equalizer parameters
125
struct equalizer_t {
126
double treble; // 5.0 = extra-crisp, -200.0 = muffled
127
long bass; // 0 = deep, 20000 = tinny
128
};
129
130
// Current frequency equalization
131
equalizer_t const& equalizer() const { return equalizer_; }
132
133
// Change frequency equalization
134
void set_equalizer( equalizer_t const& );
135
136
// Equalizer presets
137
static equalizer_t const nes_eq; // NES
138
static equalizer_t const famicom_eq; // Famicom
139
static equalizer_t const tv_eq; // TV speaker
140
141
// File save/load
142
143
// Save emulator state
144
void save_state( Nes_State* s ) const { emu.save_state( s ); }
145
blargg_err_t save_state( Auto_File_Writer ) const;
146
147
// Load state into emulator
148
void load_state( Nes_State const& );
149
blargg_err_t load_state( Auto_File_Reader );
150
151
// True if current cartridge claims it uses battery-backed memory
152
bool has_battery_ram() const { return cart()->has_battery_ram(); }
153
154
// Save current battery RAM
155
blargg_err_t save_battery_ram( Auto_File_Writer );
156
157
// Load battery RAM from file. Best called just after reset() or loading cartridge.
158
blargg_err_t load_battery_ram( Auto_File_Reader );
159
160
// Graphics
161
162
// Number of frames generated per second
163
enum { frame_rate = 60 };
164
165
// Size of fixed NES color table (including the 8 color emphasis modes)
166
enum { color_table_size = 8 * 64 };
167
168
// NES color lookup table based on standard NTSC TV decoder. Use nes_ntsc.h to
169
// generate a palette with custom parameters.
170
struct rgb_t { unsigned char red, green, blue; };
171
static rgb_t const nes_colors [color_table_size];
172
173
// Hide/show/enhance sprites. Sprite mode does not affect emulation accuracy.
174
enum sprite_mode_t {
175
sprites_hidden = 0,
176
sprites_visible = 8, // limit of 8 sprites per scanline as on NES (default)
177
sprites_enhanced = 64 // unlimited sprites per scanline (no flickering)
178
};
179
void set_sprite_mode( sprite_mode_t n ) { emu.ppu.sprite_limit = n; }
180
181
// Set range of host palette entries to use in graphics buffer; default uses
182
// all of them. Begin will be rounded up to next multiple of palette_alignment.
183
// Use frame().palette_begin to find the adjusted beginning entry used.
184
enum { palette_alignment = 64 };
185
void set_palette_range( int begin, int end = 256 );
186
187
// Access to emulated memory, for viewer/cheater/debugger
188
189
// CHR
190
byte const* chr_mem();
191
long chr_size() const;
192
void write_chr( void const*, long count, long offset );
193
194
// Nametable
195
byte* nametable_mem() { return emu.ppu.impl->nt_ram; }
196
long nametable_size() const { return 0x1000; }
197
198
// Built-in 2K memory
199
enum { low_mem_size = 0x800 };
200
byte* low_mem() { return emu.low_mem; }
201
202
// Optional 8K memory
203
enum { high_mem_size = 0x2000 };
204
byte* high_mem() { return emu.impl->sram; }
205
206
// Prg peek/poke for debuggin
207
byte peek_prg(nes_addr_t addr) const { return *static_cast<Nes_Cpu>(emu).get_code(addr); }
208
void poke_prg(nes_addr_t addr, byte value) { *static_cast<Nes_Cpu>(emu).get_code(addr) = value; }
209
byte peek_ppu(int addr) { return emu.ppu.peekaddr(addr); }
210
211
void get_regs(unsigned int *dest) const;
212
213
byte get_ppu2000() const { return emu.ppu.w2000; }
214
byte* pal_mem() { return emu.ppu.palette; }
215
byte* oam_mem() { return emu.ppu.spr_ram; }
216
217
void set_tracecb(void (*cb)(unsigned int *dest)) { emu.set_tracecb(cb); }
218
219
// End of public interface
220
public:
221
blargg_err_t set_sample_rate( long rate, class Nes_Buffer* );
222
blargg_err_t set_sample_rate( long rate, class Nes_Effects_Buffer* );
223
void irq_changed() { emu.irq_changed(); }
224
private:
225
friend class Nes_Recorder;
226
227
frame_t* frame_;
228
int buffer_height_;
229
bool fade_sound_in;
230
bool fade_sound_out;
231
virtual blargg_err_t init_();
232
233
virtual void loading_state( Nes_State const& ) { }
234
void load_state( Nes_State_ const& );
235
void save_state( Nes_State_* s ) const { emu.save_state( s ); }
236
int joypad_read_count() const { return emu.joypad_read_count; }
237
long timestamp() const { return emu.nes.frame_count; }
238
void set_timestamp( long t ) { emu.nes.frame_count = t; }
239
240
private:
241
// noncopyable
242
Nes_Emu( const Nes_Emu& );
243
Nes_Emu& operator = ( const Nes_Emu& );
244
245
// sound
246
Multi_Buffer* default_sound_buf;
247
Multi_Buffer* sound_buf;
248
unsigned sound_buf_changed_count;
249
Silent_Buffer silent_buffer;
250
equalizer_t equalizer_;
251
int channel_count_;
252
bool sound_enabled;
253
void enable_sound( bool );
254
void clear_sound_buf();
255
void fade_samples( blip_sample_t*, int size, int step );
256
257
char* host_pixel_buff;
258
char* host_pixels;
259
int host_palette_size;
260
frame_t single_frame;
261
Nes_Cart private_cart;
262
Nes_Core emu; // large; keep at end
263
264
bool init_called;
265
blargg_err_t auto_init();
266
};
267
268
inline void Nes_Emu::set_pixels( void* p, long n )
269
{
270
host_pixels = (char*) p + n;
271
emu.ppu.host_row_bytes = n;
272
}
273
274
inline byte const* Nes_Emu::chr_mem()
275
{
276
return cart()->chr_size() ? (byte*) cart()->chr() : emu.ppu.impl->chr_ram;
277
}
278
279
inline long Nes_Emu::chr_size() const
280
{
281
return cart()->chr_size() ? cart()->chr_size() : emu.ppu.chr_addr_size;
282
}
283
284
#endif
285
286