Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/quicknes/nes_emu/Nes_Mapper.cpp
2 views
1
2
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
3
4
#include "Nes_Mapper.h"
5
6
#include <string.h>
7
#include "Nes_Core.h"
8
9
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
10
can redistribute it and/or modify it under the terms of the GNU Lesser
11
General Public License as published by the Free Software Foundation; either
12
version 2.1 of the License, or (at your option) any later version. This
13
module is distributed in the hope that it will be useful, but WITHOUT ANY
14
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
16
more details. You should have received a copy of the GNU Lesser General
17
Public License along with this module; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
19
20
#include "blargg_source.h"
21
22
Nes_Mapper::Nes_Mapper()
23
{
24
emu_ = NULL;
25
static char c;
26
state = &c; // TODO: state must not be null?
27
state_size = 0;
28
}
29
30
Nes_Mapper::~Nes_Mapper()
31
{
32
}
33
34
// Sets mirroring, maps first 8K CHR in, first and last 16K of PRG,
35
// intercepts writes to upper half of memory, and clears registered state.
36
void Nes_Mapper::default_reset_state()
37
{
38
int mirroring = cart_->mirroring();
39
if ( mirroring & 8 )
40
mirror_full();
41
else if ( mirroring & 1 )
42
mirror_vert();
43
else
44
mirror_horiz();
45
46
set_chr_bank( 0, bank_8k, 0 );
47
48
set_prg_bank( 0x8000, bank_16k, 0 );
49
set_prg_bank( 0xC000, bank_16k, last_bank );
50
51
intercept_writes( 0x8000, 0x8000 );
52
53
memset( state, 0, state_size );
54
}
55
56
void Nes_Mapper::reset()
57
{
58
default_reset_state();
59
reset_state();
60
apply_mapping();
61
}
62
63
void mapper_state_t::write( const void* p, unsigned long s )
64
{
65
require( s <= max_mapper_state_size );
66
require( !size );
67
size = s;
68
memcpy( data, p, s );
69
}
70
71
int mapper_state_t::read( void* p, unsigned long s ) const
72
{
73
if ( (long) s > size )
74
s = size;
75
memcpy( p, data, s );
76
return s;
77
}
78
79
void Nes_Mapper::save_state( mapper_state_t& out )
80
{
81
out.write( state, state_size );
82
}
83
84
void Nes_Mapper::load_state( mapper_state_t const& in )
85
{
86
default_reset_state();
87
read_state( in );
88
apply_mapping();
89
}
90
91
void Nes_Mapper::read_state( mapper_state_t const& in )
92
{
93
memset( state, 0, state_size );
94
in.read( state, state_size );
95
apply_mapping();
96
}
97
98
// Timing
99
100
void Nes_Mapper::irq_changed() { emu_->irq_changed(); }
101
102
nes_time_t Nes_Mapper::next_irq( nes_time_t ) { return no_irq; }
103
104
void Nes_Mapper::a12_clocked() { }
105
106
void Nes_Mapper::run_until( nes_time_t ) { }
107
108
void Nes_Mapper::end_frame( nes_time_t ) { }
109
110
bool Nes_Mapper::ppu_enabled() const { return emu().ppu.w2001 & 0x08; }
111
112
// Sound
113
114
int Nes_Mapper::channel_count() const { return 0; }
115
116
void Nes_Mapper::set_channel_buf( int, Blip_Buffer* ) { require( false ); }
117
118
void Nes_Mapper::set_treble( blip_eq_t const& ) { }
119
120
// Memory mapping
121
122
void Nes_Mapper::set_prg_bank( nes_addr_t addr, bank_size_t bs, int bank )
123
{
124
require( addr >= 0x2000 ); // can't remap low-memory
125
126
int bank_size = 1 << bs;
127
require( addr % bank_size == 0 ); // must be aligned
128
129
int bank_count = cart_->prg_size() >> bs;
130
if ( bank < 0 )
131
bank += bank_count;
132
133
if ( bank >= bank_count )
134
{
135
check( !(cart_->prg_size() & (cart_->prg_size() - 1)) ); // ensure PRG size is power of 2
136
bank %= bank_count;
137
}
138
139
emu().map_code( addr, bank_size, cart_->prg() + (bank << bs) );
140
141
if ( unsigned (addr - 0x6000) < 0x2000 )
142
emu().enable_prg_6000();
143
}
144
145
void Nes_Mapper::set_chr_bank( nes_addr_t addr, bank_size_t bs, int bank )
146
{
147
emu().ppu.render_until( emu().clock() );
148
emu().ppu.set_chr_bank( addr, 1 << bs, bank << bs );
149
}
150
151
void Nes_Mapper::set_chr_bank_ex( nes_addr_t addr, bank_size_t bs, int bank )
152
{
153
emu().ppu.render_until( emu().clock() );
154
emu().ppu.set_chr_bank_ex( addr, 1 << bs, bank << bs );
155
}
156
157
void Nes_Mapper::mirror_manual( int page0, int page1, int page2, int page3 )
158
{
159
emu().ppu.render_bg_until( emu().clock() );
160
emu().ppu.set_nt_banks( page0, page1, page2, page3 );
161
}
162
163
#ifndef NDEBUG
164
int Nes_Mapper::handle_bus_conflict( nes_addr_t addr, int data )
165
{
166
if ( emu().Nes_Cpu::get_code( addr ) [0] != data )
167
dprintf( "Mapper write had bus conflict\n" );
168
return data;
169
}
170
#endif
171
172
// Mapper registration
173
174
int const max_mappers = 32;
175
Nes_Mapper::mapping_t Nes_Mapper::mappers [max_mappers] =
176
{
177
{ 0, Nes_Mapper::make_nrom },
178
{ 1, Nes_Mapper::make_mmc1 },
179
{ 2, Nes_Mapper::make_unrom },
180
{ 3, Nes_Mapper::make_cnrom },
181
{ 4, Nes_Mapper::make_mmc3 },
182
{ 7, Nes_Mapper::make_aorom }
183
};
184
static int mapper_count = 6; // to do: keep synchronized with pre-supplied mappers above
185
186
Nes_Mapper::creator_func_t Nes_Mapper::get_mapper_creator( int code )
187
{
188
for ( int i = 0; i < mapper_count; i++ )
189
{
190
if ( mappers [i].code == code )
191
return mappers [i].func;
192
}
193
return NULL;
194
}
195
196
void Nes_Mapper::register_mapper( int code, creator_func_t func )
197
{
198
// Catch attempted registration of a different creation function for same mapper code
199
require( !get_mapper_creator( code ) || get_mapper_creator( code ) == func );
200
require( mapper_count < max_mappers ); // fixed liming on number of registered mappers
201
202
mapping_t& m = mappers [mapper_count++];
203
m.code = code;
204
m.func = func;
205
}
206
207
Nes_Mapper* Nes_Mapper::create( Nes_Cart const* cart, Nes_Core* emu )
208
{
209
Nes_Mapper::creator_func_t func = get_mapper_creator( cart->mapper_code() );
210
if ( !func )
211
return NULL;
212
213
// to do: out of memory will be reported as unsupported mapper
214
Nes_Mapper* mapper = func();
215
if ( mapper )
216
{
217
mapper->cart_ = cart;
218
mapper->emu_ = emu;
219
}
220
return mapper;
221
}
222
223
224