Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/lynx/cart.cpp
2 views
1
//
2
// Copyright (c) 2004 K. Wilkins
3
//
4
// This software is provided 'as-is', without any express or implied warranty.
5
// In no event will the authors be held liable for any damages arising from
6
// the use of this software.
7
//
8
// Permission is granted to anyone to use this software for any purpose,
9
// including commercial applications, and to alter it and redistribute it
10
// freely, subject to the following restrictions:
11
//
12
// 1. The origin of this software must not be misrepresented; you must not
13
// claim that you wrote the original software. If you use this software
14
// in a product, an acknowledgment in the product documentation would be
15
// appreciated but is not required.
16
//
17
// 2. Altered source versions must be plainly marked as such, and must not
18
// be misrepresented as being the original software.
19
//
20
// 3. This notice may not be removed or altered from any source distribution.
21
//
22
23
//////////////////////////////////////////////////////////////////////////////
24
// Handy - An Atari Lynx Emulator //
25
// Copyright (c) 1996,1997 //
26
// K. Wilkins //
27
//////////////////////////////////////////////////////////////////////////////
28
// Lynx Cartridge Class //
29
//////////////////////////////////////////////////////////////////////////////
30
// //
31
// This class emulates the Lynx cartridge interface, given a filename it //
32
// will contstruct a cartridge object via the constructor. //
33
// //
34
// K. Wilkins //
35
// August 1997 //
36
// //
37
//////////////////////////////////////////////////////////////////////////////
38
// Revision History: //
39
// ----------------- //
40
// //
41
// 01Aug1997 KW Document header added & class documented. //
42
// //
43
//////////////////////////////////////////////////////////////////////////////
44
45
#define CART_CPP
46
47
#include "system.h"
48
49
#include <algorithm>
50
#include <string.h>
51
#include "cart.h"
52
53
/*
54
bool CCart::TestMagic(const uint8 *data, uint32 size)
55
{
56
if(size <= HEADER_RAW_SIZE)
57
return(FALSE);
58
59
if(memcmp(data, "LYNX", 4) || data[8] != 0x01)
60
return(FALSE);
61
62
return(TRUE);
63
}
64
*/
65
66
CCart::CCart(const uint8 *gamedata, uint32 gamesize, int pagesize0, int pagesize1)
67
{
68
CTYPE banktype0,banktype1;
69
70
switch(pagesize0)
71
{
72
default:
73
// warn?
74
case 0x000:
75
banktype0=UNUSED;
76
mMaskBank0=0;
77
mShiftCount0=0;
78
mCountMask0=0;
79
break;
80
case 0x100:
81
banktype0=C64K;
82
mMaskBank0=0x00ffff;
83
mShiftCount0=8;
84
mCountMask0=0x0ff;
85
break;
86
case 0x200:
87
banktype0=C128K;
88
mMaskBank0=0x01ffff;
89
mShiftCount0=9;
90
mCountMask0=0x1ff;
91
break;
92
case 0x400:
93
banktype0=C256K;
94
mMaskBank0=0x03ffff;
95
mShiftCount0=10;
96
mCountMask0=0x3ff;
97
break;
98
case 0x800:
99
banktype0=C512K;
100
mMaskBank0=0x07ffff;
101
mShiftCount0=11;
102
mCountMask0=0x7ff;
103
break;
104
}
105
106
switch(pagesize1)
107
{
108
default:
109
// warn?
110
case 0x000:
111
banktype1=UNUSED;
112
mMaskBank1=0;
113
mShiftCount1=0;
114
mCountMask1=0;
115
break;
116
case 0x100:
117
banktype1=C64K;
118
mMaskBank1=0x00ffff;
119
mShiftCount1=8;
120
mCountMask1=0x0ff;
121
break;
122
case 0x200:
123
banktype1=C128K;
124
mMaskBank1=0x01ffff;
125
mShiftCount1=9;
126
mCountMask1=0x1ff;
127
break;
128
case 0x400:
129
banktype1=C256K;
130
mMaskBank1=0x03ffff;
131
mShiftCount1=10;
132
mCountMask1=0x3ff;
133
break;
134
case 0x800:
135
banktype1=C512K;
136
mMaskBank1=0x07ffff;
137
mShiftCount1=11;
138
mCountMask1=0x7ff;
139
break;
140
}
141
142
// Make some space for the new carts
143
mCartBank0 = new uint8[mMaskBank0+1];
144
mCartBank1 = new uint8[mMaskBank1+1];
145
146
// Set default bank
147
mBank=bank0;
148
149
// Initialiase
150
std::memset(mCartBank0, DEFAULT_CART_CONTENTS, mMaskBank0 + 1);
151
std::memset(mCartBank1, DEFAULT_CART_CONTENTS, mMaskBank1 + 1);
152
153
// Read in the BANK0 bytes
154
if(mMaskBank0)
155
{
156
int size = std::min(gamesize, mMaskBank0+1);
157
std::memcpy(mCartBank0, gamedata, size);
158
gamedata += size;
159
gamesize -= size;
160
}
161
162
// Read in the BANK1 bytes
163
if(mMaskBank1)
164
{
165
int size = std::min(gamesize, mMaskBank1+1);
166
std::memcpy(mCartBank1, gamedata, size);
167
gamedata += size;
168
}
169
170
// As this is a cartridge boot unset the boot address
171
// mSystem.gCPUBootAddress=0;
172
173
// Dont allow an empty Bank1 - Use it for shadow SRAM/EEPROM
174
if(banktype1==UNUSED)
175
{
176
// Delete the single byte allocated earlier
177
delete[] mCartBank1;
178
// Allocate some new memory for us
179
banktype1=C64K;
180
mMaskBank1=0x00ffff;
181
mShiftCount1=8;
182
mCountMask1=0x0ff;
183
mCartBank1 = (uint8*) new uint8[mMaskBank1+1];
184
std::memset(mCartBank1, DEFAULT_RAM_CONTENTS, mMaskBank1 + 1);
185
mWriteEnableBank1=TRUE;
186
mCartRAM=TRUE;
187
}
188
}
189
190
CCart::~CCart()
191
{
192
delete[] mCartBank0;
193
delete[] mCartBank1;
194
}
195
196
197
void CCart::Reset()
198
{
199
mCounter = 0;
200
mShifter = 0;
201
mAddrData = 0;
202
mStrobe = 0;
203
last_strobe = 0;
204
}
205
206
INLINE void CCart::Poke(uint32 addr, uint8 data)
207
{
208
if(mBank==bank0)
209
{
210
if(mWriteEnableBank0 && false) // can never write as there is no ram
211
mCartBank0[addr&mMaskBank0]=data;
212
}
213
else
214
{
215
if(mWriteEnableBank1 && mCartRAM) // can only write if it's actually ram
216
mCartBank1[addr&mMaskBank1]=data;
217
}
218
}
219
220
221
INLINE uint8 CCart::Peek(uint32 addr)
222
{
223
if(mBank==bank0)
224
{
225
return(mCartBank0[addr&mMaskBank0]);
226
}
227
else
228
{
229
return(mCartBank1[addr&mMaskBank1]);
230
}
231
}
232
233
234
void CCart::CartAddressStrobe(bool strobe)
235
{
236
mStrobe=strobe;
237
238
if(mStrobe) mCounter=0;
239
240
//
241
// Either of the two below seem to work OK.
242
//
243
// if(!strobe && last_strobe)
244
//
245
if(mStrobe && !last_strobe)
246
{
247
// Clock a bit into the shifter
248
mShifter=mShifter<<1;
249
mShifter+=mAddrData?1:0;
250
mShifter&=0xff;
251
}
252
last_strobe=mStrobe;
253
}
254
255
void CCart::CartAddressData(bool data)
256
{
257
mAddrData=data;
258
}
259
260
261
void CCart::Poke0(uint8 data)
262
{
263
if(mWriteEnableBank0 && false) // can never write as there is no ram
264
{
265
uint32 address=(mShifter<<mShiftCount0)+(mCounter&mCountMask0);
266
mCartBank0[address&mMaskBank0]=data;
267
}
268
if(!mStrobe)
269
{
270
mCounter++;
271
mCounter&=0x07ff;
272
}
273
}
274
275
void CCart::Poke1(uint8 data)
276
{
277
if(mWriteEnableBank1 && mCartRAM) // can only write if it's actually ram
278
{
279
uint32 address=(mShifter<<mShiftCount1)+(mCounter&mCountMask1);
280
mCartBank1[address&mMaskBank1]=data;
281
}
282
if(!mStrobe)
283
{
284
mCounter++;
285
mCounter&=0x07ff;
286
}
287
}
288
289
290
uint8 CCart::Peek0(void)
291
{
292
uint32 address=(mShifter<<mShiftCount0)+(mCounter&mCountMask0);
293
uint8 data=mCartBank0[address&mMaskBank0];
294
295
if(!mStrobe)
296
{
297
mCounter++;
298
mCounter&=0x07ff;
299
}
300
301
return data;
302
}
303
304
uint8 CCart::Peek1(void)
305
{
306
uint32 address=(mShifter<<mShiftCount1)+(mCounter&mCountMask1);
307
uint8 data=mCartBank1[address&mMaskBank1];
308
309
if(!mStrobe)
310
{
311
mCounter++;
312
mCounter&=0x07ff;
313
}
314
315
return data;
316
}
317
318
319
320
bool CCart::GetSaveRamPtr(int &size, uint8 *&data)
321
{
322
if (mCartRAM)
323
{
324
size = mMaskBank1 + 1;
325
data = mCartBank1;
326
return true;
327
}
328
else
329
{
330
return false;
331
}
332
}
333
334
void CCart::GetReadOnlyPtrs(int &s0, uint8 *&p0, int &s1, uint8 *&p1)
335
{
336
s0 = mMaskBank0 + 1;
337
s1 = mMaskBank1 + 1;
338
p0 = mCartBank0;
339
p1 = mCartBank1;
340
}
341
342
SYNCFUNC(CCart)
343
{
344
NSS(mWriteEnableBank0);
345
NSS(mWriteEnableBank1);
346
NSS(mCartRAM);
347
348
EBS(mBank, 0);
349
EVS(mBank, bank0, 0);
350
EVS(mBank, bank1, 1);
351
EVS(mBank, ram, 2);
352
EVS(mBank, cpu, 3);
353
EES(mBank, bank0);
354
355
NSS(mMaskBank0);
356
NSS(mMaskBank1);
357
if (false)
358
PSS(mCartBank0, mMaskBank0 + 1);
359
if (mCartRAM)
360
PSS(mCartBank1, mMaskBank1 + 1);
361
362
NSS(mCounter);
363
NSS(mShifter);
364
NSS(mAddrData);
365
NSS(mStrobe);
366
367
NSS(mShiftCount0);
368
NSS(mCountMask0);
369
NSS(mShiftCount1);
370
NSS(mCountMask1);
371
372
NSS(last_strobe);
373
}
374
375