Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/quicknes/nes_emu/Mapper_Mmc5.cpp
2 views
1
2
// NES MMC5 mapper, currently only tailored for Castlevania 3 (U)
3
4
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
5
6
#include "Nes_Mapper.h"
7
8
#include "Nes_Core.h"
9
#include <string.h>
10
11
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
12
can redistribute it and/or modify it under the terms of the GNU Lesser
13
General Public License as published by the Free Software Foundation; either
14
version 2.1 of the License, or (at your option) any later version. This
15
module is distributed in the hope that it will be useful, but WITHOUT ANY
16
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
18
more details. You should have received a copy of the GNU Lesser General
19
Public License along with this module; if not, write to the Free Software
20
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
21
22
#include "blargg_source.h"
23
24
struct mmc5_state_t
25
{
26
enum { reg_count = 0x30 };
27
byte regs [0x30];
28
byte irq_enabled;
29
};
30
// to do: finalize state format
31
BOOST_STATIC_ASSERT( sizeof (mmc5_state_t) == 0x31 );
32
33
class Mapper_Mmc5 : public Nes_Mapper, mmc5_state_t {
34
nes_time_t irq_time;
35
public:
36
Mapper_Mmc5()
37
{
38
mmc5_state_t* state = this;
39
register_state( state, sizeof *state );
40
}
41
42
virtual void reset_state()
43
{
44
irq_time = no_irq;
45
regs [0x00] = 2;
46
regs [0x01] = 3;
47
regs [0x14] = 0x7f;
48
regs [0x15] = 0x7f;
49
regs [0x16] = 0x7f;
50
regs [0x17] = 0x7f;
51
}
52
53
virtual void read_state( mapper_state_t const& in )
54
{
55
Nes_Mapper::read_state( in );
56
irq_time = no_irq;
57
}
58
59
enum { regs_addr = 0x5100 };
60
61
virtual void apply_mapping();
62
63
virtual nes_time_t next_irq( nes_time_t )
64
{
65
if ( irq_enabled & 0x80 )
66
return irq_time;
67
68
return no_irq;
69
}
70
71
virtual bool write_intercepted( nes_time_t time, nes_addr_t addr, int data )
72
{
73
int reg = addr - regs_addr;
74
if ( (unsigned) reg < reg_count )
75
{
76
regs [reg] = data;
77
switch ( reg )
78
{
79
case 0x05:
80
mirror_manual( data & 3, data >> 2 & 3,
81
data >> 4 & 3, data >> 6 & 3 );
82
break;
83
84
case 0x15:
85
set_prg_bank( 0x8000, bank_16k, data >> 1 & 0x3f );
86
break;
87
88
case 0x16:
89
set_prg_bank( 0xC000, bank_8k, data & 0x7f );
90
break;
91
92
case 0x17:
93
set_prg_bank( 0xE000, bank_8k, data & 0x7f );
94
break;
95
96
case 0x20:
97
case 0x21:
98
case 0x22:
99
case 0x23:
100
case 0x28:
101
case 0x29:
102
case 0x2a:
103
case 0x2b:
104
set_chr_bank( ((reg >> 1 & 4) + (reg & 3)) * 0x400, bank_1k, data );
105
break;
106
}
107
check( (regs [0x00] & 3) == 2 );
108
check( (regs [0x01] & 3) == 3 );
109
}
110
else if ( addr == 0x5203 )
111
{
112
irq_time = no_irq;
113
if ( data && data < 240 )
114
{
115
irq_time = (341 * 21 + 128 + (data * 341)) / 3;
116
if ( irq_time < time )
117
irq_time = no_irq;
118
}
119
irq_changed();
120
}
121
else if ( addr == 0x5204 )
122
{
123
irq_enabled = data;
124
irq_changed();
125
}
126
else
127
{
128
return false;
129
}
130
131
return true;
132
}
133
134
virtual void write( nes_time_t, nes_addr_t, int ) { }
135
};
136
137
void Mapper_Mmc5::apply_mapping()
138
{
139
static unsigned char list [] = {
140
0x05, 0x15, 0x16, 0x17,
141
0x20, 0x21, 0x22, 0x23,
142
0x28, 0x29, 0x2a, 0x2b
143
};
144
145
for ( int i = 0; i < (int) sizeof list; i++ )
146
write_intercepted( 0, regs_addr + list [i], regs [list [i]] );
147
intercept_writes( 0x5100, 0x200 );
148
}
149
150
void register_mmc5_mapper();
151
void register_mmc5_mapper()
152
{
153
register_mapper<Mapper_Mmc5>( 5 );
154
}
155
156
157