8
8
// SS SS tt ee ll ll aa aa
9
9
// SSSS ttt eeeee llll llll aaaaa
11
// Copyright (c) 1995-2008 by Bradford W. Mott and the Stella team
11
// Copyright (c) 1995-2010 by Bradford W. Mott, Stephen Anthony
12
// and the Stella Team
13
// See the file "license" for information on usage and redistribution of
14
// See the file "License.txt" for information on usage and redistribution of
14
15
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16
// $Id: Cart3F.cxx,v 1.18 2008/03/28 23:29:13 stephena Exp $
17
// $Id: Cart3F.cxx 2012 2010-04-14 22:35:46Z stephena $
17
18
//============================================================================
21
23
#include "System.hxx"
30
32
myImage = new uInt8[mySize];
32
34
// Copy the ROM image into my buffer
33
for(uInt32 addr = 0; addr < mySize; ++addr)
35
myImage[addr] = image[addr];
35
memcpy(myImage, image, mySize);
37
// Remember startup bank
39
41
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
45
47
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
46
48
void Cartridge3F::reset()
48
// We'll map bank 0 into the first segment upon reset
50
// We'll map the startup bank into the first segment upon reset
52
54
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
62
64
// Set the page accessing methods for the hot spots (for 100% emulation
63
65
// we need to chain any accesses below 0x40 to the TIA. Our poke() method
64
66
// does this via mySystem->tiaPoke(...), at least until we come up with a
65
// cleaner way to do it.)
67
// cleaner way to do it).
66
68
System::PageAccess access;
69
access.directPeekBase = 0;
70
access.directPokeBase = 0;
72
access.type = System::PA_READWRITE;
67
73
for(uInt32 i = 0x00; i < 0x40; i += (1 << shift))
69
access.directPeekBase = 0;
70
access.directPokeBase = 0;
72
74
mySystem->setPageAccess(i >> shift, access);
75
76
// Setup the second segment to always point to the last ROM slice
77
access.directPokeBase = 0;
79
access.type = System::PA_READ;
76
80
for(uInt32 j = 0x1800; j < 0x2000; j += (1 << shift))
79
82
access.directPeekBase = &myImage[(mySize - 2048) + (j & 0x07FF)];
80
access.directPokeBase = 0;
81
83
mySystem->setPageAccess(j >> shift, access);
84
// Install pages for bank 0 into the first segment
86
// Install pages for startup bank into the first segment
88
90
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
89
91
uInt8 Cartridge3F::peek(uInt16 address)
91
address = address & 0x0FFF;
93
95
if(address < 0x0800)
95
return myImage[(address & 0x07FF) + myCurrentBank * 2048];
97
return myImage[(address & 0x07FF) + (myCurrentBank << 11)];
103
105
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
104
void Cartridge3F::poke(uInt16 address, uInt8 value)
106
bool Cartridge3F::poke(uInt16 address, uInt8 value)
106
address = address & 0x0FFF;
108
110
// Switch banks if necessary
109
111
if(address <= 0x003F)
116
// Pass the poke through to the TIA. In a real Atari, both the cart and the
117
// TIA see the address lines, and both react accordingly. In Stella, each
118
// 64-byte chunk of address space is "owned" by only one device. If we
119
// don't chain the poke to the TIA, then the TIA can't see it...
114
120
mySystem->tia().poke(address, value);
117
125
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
118
126
void Cartridge3F::bank(uInt16 bank)
120
if(myBankLocked) return;
128
if(bankLocked()) return;
122
130
// Make sure the bank they're asking for is reasonable
123
if((uInt32)bank * 2048 < mySize)
131
if(((uInt32)bank << 11) < mySize)
125
133
myCurrentBank = bank;
129
137
// Oops, the bank they're asking for isn't valid so let's wrap it
130
138
// around to a valid bank number
131
myCurrentBank = bank % (mySize / 2048);
139
myCurrentBank = bank % (mySize >> 11);
134
uInt32 offset = myCurrentBank * 2048;
142
uInt32 offset = myCurrentBank << 11;
135
143
uInt16 shift = mySystem->pageShift();
137
145
// Setup the page access methods for the current bank
138
146
System::PageAccess access;
147
access.directPokeBase = 0;
139
148
access.device = this;
140
access.directPokeBase = 0;
149
access.type = System::PA_READ;
142
151
// Map ROM image into the system
143
152
for(uInt32 address = 0x1000; address < 0x1800; address += (1 << shift))
145
154
access.directPeekBase = &myImage[offset + (address & 0x07FF)];
146
155
mySystem->setPageAccess(address >> shift, access);
157
myBankChanged = true;
150
160
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
151
int Cartridge3F::bank()
161
uInt16 Cartridge3F::bank() const
153
163
return myCurrentBank;
156
166
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
157
int Cartridge3F::bankCount()
167
uInt16 Cartridge3F::bankCount() const
159
return mySize / 2048;
162
172
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
163
173
bool Cartridge3F::patch(uInt16 address, uInt8 value)
165
address = address & 0x0FFF;
166
177
if(address < 0x0800)
168
myImage[(address & 0x07FF) + myCurrentBank * 2048] = value;
178
myImage[(address & 0x07FF) + (myCurrentBank << 11)] = value;
172
180
myImage[(address & 0x07FF) + mySize - 2048] = value;
182
return myBankChanged = true;
177
185
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
178
uInt8* Cartridge3F::getImage(int& size)
186
const uInt8* Cartridge3F::getImage(int& size) const
184
192
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
185
193
bool Cartridge3F::save(Serializer& out) const
187
string cart = name();
195
const string& cart = name();