1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/Memory/SlotManager.c,v $
3 **
4 ** $Revision: 1.8 $
5 **
6 ** $Date: 2008-03-30 18:38:42 $
7 **
8 ** More info: http://www.bluemsx.com
9 **
10 ** Copyright (C) 2003-2006 Daniel Vik
11 **
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License as published by
14 ** the Free Software Foundation; either version 2 of the License, or
15 ** (at your option) any later version.
16 **
17 ** This program is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ** GNU General Public License for more details.
21 **
22 ** You should have received a copy of the GNU General Public License
23 ** along with this program; if not, write to the Free Software
24 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 **
26 ******************************************************************************
27 */
28 #include "SlotManager.h"
29 #include "SaveState.h"
30 #include "Led.h"
31 #include "IoPort.h"
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdio.h>
35
36 typedef struct {
37 UInt8* pageData;
38 int readEnable;
39 int writeEnable;
40 } RamSlotState;
41
42 typedef struct {
43 int subslotted;
44 UInt8 state;
45 UInt8 substate;
46 UInt8 sslReg;
47 } PrimarySlotState;
48
49
50 typedef struct {
51 UInt16 startpage;
52 UInt16 pages;
53 UInt8* pageData;
54 int writeEnable;
55 int readEnable;
56 SlotRead read;
57 SlotRead peek;
58 SlotWrite write;
59 SlotEject eject;
60 void* ref;
61 } Slot;
62
63 static RamSlotState ramslot[8];
64 static PrimarySlotState pslot[4];
65 static Slot slotTable[4][4][8];
66 static Slot slotAddr0;
67 static UInt8 emptyRAM[0x2000];
68 static Int32 initialized;
69
slotMapRamPage(int slot,int sslot,int page)70 void slotMapRamPage(int slot, int sslot, int page)
71 {
72 ramslot[page].readEnable = slotTable[slot][sslot][page].readEnable;
73 ramslot[page].writeEnable = slotTable[slot][sslot][page].writeEnable;
74 ramslot[page].pageData = slotTable[slot][sslot][page].pageData;
75 }
76
slotSetRamSlot(int slot,int psl)77 void slotSetRamSlot(int slot, int psl)
78 {
79 int ssl;
80
81 pslot[slot].state = psl;
82 pslot[slot].substate = (pslot[psl].sslReg >> (slot * 2)) & 3;
83
84 ssl = pslot[psl].subslotted ? pslot[slot].substate : 0;
85
86 slotMapRamPage(psl, ssl, 2 * slot);
87 slotMapRamPage(psl, ssl, 2 * slot + 1);
88 }
89
slotGetRamSlot(int page)90 int slotGetRamSlot(int page)
91 {
92 int i;
93 for (i = 0; i < 4; i++) {
94 if (pslot[i].state == page) {
95 return i;
96 }
97 }
98 return 0;
99 }
100
slotMapPage(int slot,int sslot,int page,UInt8 * pageData,int readEnable,int writeEnable)101 void slotMapPage(int slot, int sslot, int page, UInt8* pageData,
102 int readEnable, int writeEnable)
103 {
104 if (!initialized) {
105 return;
106 }
107
108 slotTable[slot][sslot][page].readEnable = readEnable;
109 slotTable[slot][sslot][page].writeEnable = writeEnable;
110
111 if (pageData != NULL) {
112 slotTable[slot][sslot][page].pageData = pageData;
113 }
114 #if 0
115 if (pslot[page >> 1].state == slot && (!pslot[slot].subslotted || sslot == 2 || pslot[page >> 1].substate == sslot)) {
116 slotMapRamPage(slot, sslot, page);
117 }
118 #else
119 if (pslot[page >> 1].state == slot &&
120 (!pslot[slot].subslotted || pslot[page >> 1].substate == sslot))
121 {
122 slotMapRamPage(slot, sslot, page);
123 }
124 #endif
125 }
126
slotUpdatePage(int slot,int sslot,int page,UInt8 * pageData,int readEnable,int writeEnable)127 void slotUpdatePage(int slot, int sslot, int page, UInt8* pageData,
128 int readEnable, int writeEnable)
129 {
130 if (!initialized) {
131 return;
132 }
133
134 slotMapPage(slot, sslot, page, pageData, readEnable, writeEnable);
135 return;
136 slotTable[slot][sslot][page].readEnable = readEnable;
137 slotTable[slot][sslot][page].writeEnable = writeEnable;
138
139 if (pageData != NULL) {
140 slotTable[slot][sslot][page].pageData = pageData;
141 }
142 }
143
slotUnmapPage(int slot,int sslot,int page)144 void slotUnmapPage(int slot, int sslot, int page)
145 {
146 if (!initialized) {
147 return;
148 }
149
150 slotTable[slot][sslot][page].readEnable = 0;
151 slotTable[slot][sslot][page].writeEnable = 1;
152 slotTable[slot][sslot][page].pageData = emptyRAM;
153
154 if (pslot[page >> 1].state == slot &&
155 (!pslot[slot].subslotted || pslot[page >> 1].substate == sslot))
156 {
157 slotMapRamPage(slot, sslot, page);
158 }
159 }
160
slotRegisterWrite0(SlotWrite writeCb,void * ref)161 void slotRegisterWrite0(SlotWrite writeCb, void* ref)
162 {
163 if (!initialized) {
164 return;
165 }
166
167 slotAddr0.read = NULL;
168 slotAddr0.write = writeCb;
169 slotAddr0.eject = NULL;
170 slotAddr0.ref = ref;
171 }
172
slotUnregisterWrite0()173 void slotUnregisterWrite0() {
174 if (!initialized) {
175 return;
176 }
177
178 memset(&slotAddr0, 0, sizeof(Slot));
179 }
180
slotRegister(int slot,int sslot,int startpage,int pages,SlotRead readCb,SlotRead peekCb,SlotWrite writeCb,SlotEject ejectCb,void * ref)181 void slotRegister(int slot, int sslot, int startpage, int pages,
182 SlotRead readCb, SlotRead peekCb, SlotWrite writeCb, SlotEject ejectCb, void* ref)
183 {
184 Slot* slotInfo;
185
186 if (!initialized) {
187 return;
188 }
189
190 slotInfo = &slotTable[slot][sslot][startpage];
191
192 slotInfo->pages = pages;
193
194 while (pages--) {
195 slotInfo->startpage = startpage;
196 slotInfo->read = readCb;
197 slotInfo->peek = peekCb;
198 slotInfo->write = writeCb;
199 slotInfo->eject = ejectCb;
200 slotInfo->ref = ref;
201 slotInfo++;
202 }
203 }
204
205
slotUnregister(int slot,int sslot,int startpage)206 void slotUnregister(int slot, int sslot, int startpage)
207 {
208 Slot* slotInfo;
209 int pages;
210
211 if (!initialized) {
212 return;
213 }
214
215 slotInfo = &slotTable[slot][sslot][startpage];
216 pages = slotInfo->pages;
217
218 while (pages--) {
219 memset(slotInfo, 0, sizeof(Slot));
220 slotUnmapPage(slot, sslot, startpage + pages);
221 slotInfo++;
222 }
223 }
224
slotRemove(int slot,int sslot)225 void slotRemove(int slot, int sslot)
226 {
227 int page;
228
229 if (!initialized) {
230 return;
231 }
232
233 for (page = 0; page < 8; page++) {
234 Slot* slotInfo = &slotTable[slot][sslot][page];
235 if (slotInfo->eject != NULL) {
236 slotInfo->eject(slotInfo->ref);
237 }
238 }
239 }
240
slotSetSubslotted(int slot,int subslotted)241 void slotSetSubslotted(int slot, int subslotted)
242 {
243 if (!initialized) {
244 return;
245 }
246
247 pslot[slot].subslotted = subslotted;
248 }
249
slotManagerReset()250 void slotManagerReset()
251 {
252 int page;
253
254 if (!initialized) {
255 return;
256 }
257
258 for (page = 0; page < 4; page++) {
259 pslot[page].state = 0;
260 pslot[page].substate = 0;
261
262 slotMapRamPage(0, 0, 2 * page);
263 slotMapRamPage(0, 0, 2 * page + 1);
264 }
265 }
266
slotManagerCreate()267 void slotManagerCreate()
268 {
269 int slot;
270 int sslot;
271 int page;
272
273 memset(emptyRAM, 0xff, 0x2000);
274 memset(ramslot, 0, sizeof(ramslot));
275 memset(pslot, 0, sizeof(pslot));
276 memset(slotTable, 0, sizeof(slotTable));
277 memset(&slotAddr0, 0, sizeof(slotAddr0));
278
279 for (slot = 0; slot < 4; slot++) {
280 for (sslot = 0; sslot < 4; sslot++) {
281 for (page = 0; page < 8; page++) {
282 slotUnmapPage(slot, sslot, page);
283 }
284 }
285 }
286
287 initialized = 1;
288 }
289
slotManagerDestroy()290 void slotManagerDestroy()
291 {
292 initialized = 0;
293 }
294
slotPeek(void * ref,UInt16 address)295 UInt8 slotPeek(void* ref, UInt16 address)
296 {
297 Slot* slotInfo;
298 int psl;
299 int ssl;
300
301 if (!initialized) {
302 return 0xff;
303 }
304
305 if (address == 0xffff) {
306 UInt8 sslReg = pslot[3].state;
307 if (pslot[sslReg].subslotted) {
308 return ~pslot[sslReg].sslReg;
309 }
310 }
311
312 if (ramslot[address >> 13].readEnable) {
313 return ramslot[address >> 13].pageData[address & 0x1fff];
314 }
315
316 psl = pslot[address >> 14].state;
317 ssl = pslot[psl].subslotted ? pslot[address >> 14].substate : 0;
318
319 slotInfo = &slotTable[psl][ssl][address >> 13];
320
321 if (slotInfo->peek != NULL) {
322 address -= slotInfo->startpage << 13;
323 return slotInfo->peek(slotInfo->ref, address);
324 }
325
326 return 0xff;
327 }
328
slotRead(void * ref,UInt16 address)329 UInt8 slotRead(void* ref, UInt16 address)
330 {
331 Slot* slotInfo;
332 int psl;
333 int ssl;
334
335 if (!initialized) {
336 return 0xff;
337 }
338
339 if (address == 0xffff) {
340 UInt8 sslReg = pslot[3].state;
341 if (pslot[sslReg].subslotted) {
342 return ~pslot[sslReg].sslReg;
343 }
344 }
345
346 if (ramslot[address >> 13].readEnable) {
347 return ramslot[address >> 13].pageData[address & 0x1fff];
348 }
349
350 psl = pslot[address >> 14].state;
351 ssl = pslot[psl].subslotted ? pslot[address >> 14].substate : 0;
352
353 slotInfo = &slotTable[psl][ssl][address >> 13];
354
355 if (slotInfo->read != NULL) {
356 address -= slotInfo->startpage << 13;
357 return slotInfo->read(slotInfo->ref, address);
358 }
359
360 return 0xff;
361 }
362
slotWrite(void * ref,UInt16 address,UInt8 value)363 void slotWrite(void* ref, UInt16 address, UInt8 value)
364 {
365 Slot* slotInfo;
366 int psl;
367 int ssl;
368 int page;
369
370 if (!initialized) {
371 return;
372 }
373
374 if (address == 0xffff) {
375 UInt8 pslReg = pslot[3].state;
376
377 if (pslot[pslReg].subslotted) {
378 // printf("SW: %d %d %d %d\n", (value>>0)&3, (value>>2)&3, (value>>4)&3, (value>>6)&3);
379 pslot[pslReg].sslReg = value;
380
381 for (page = 0; page < 4; page++) {
382 if(pslot[page].state == pslReg) {
383 pslot[page].substate = value & 3;
384 slotMapRamPage(pslReg, value & 3, 2 * page);
385 slotMapRamPage(pslReg, value & 3, 2 * page + 1);
386 }
387 value >>= 2;
388 }
389
390 return;
391 }
392 }
393
394 if (address == 0) {
395 if (slotAddr0.write != NULL) {
396 slotAddr0.write(slotAddr0.ref, address, value);
397 return;
398 }
399 }
400
401 if (ramslot[address >> 13].writeEnable) {
402 ramslot[address >> 13].pageData[address & 0x1FFF] = value;
403 return;
404 }
405
406 psl = pslot[address >> 14].state;
407 ssl = pslot[psl].subslotted ? pslot[address >> 14].substate : 0;
408
409 slotInfo = &slotTable[psl][ssl][address >> 13];
410
411 if (slotInfo->write != NULL) {
412 address -= slotInfo->startpage << 13;
413 slotInfo->write(slotInfo->ref, address, value);
414 }
415 }
416
slotSaveState()417 void slotSaveState()
418 {
419 SaveState* state;
420 char tag[32];
421 int i;
422
423 if (!initialized) {
424 return;
425 }
426
427 state = saveStateOpenForWrite("slotManager");
428
429 for (i = 0; i < 4; i++) {
430 sprintf(tag, "subslotted%d", i);
431 saveStateSet(state, tag, pslot[i].subslotted);
432
433 sprintf(tag, "state%d", i);
434 saveStateSet(state, tag, pslot[i].state);
435
436 sprintf(tag, "substate%d", i);
437 saveStateSet(state, tag, pslot[i].substate);
438
439 sprintf(tag, "sslReg%d", i);
440 saveStateSet(state, tag, pslot[i].sslReg);
441 }
442
443 saveStateClose(state);
444 }
445
slotLoadState()446 void slotLoadState()
447 {
448 SaveState* state;
449 char tag[32];
450 int page;
451 int i;
452
453 if (!initialized) {
454 return;
455 }
456
457 state = saveStateOpenForRead("slotManager");
458
459 for (i = 0; i < 4; i++) {
460 sprintf(tag, "subslotted%d", i);
461 pslot[i].subslotted = saveStateGet(state, tag, 0);
462
463 sprintf(tag, "state%d", i);
464 pslot[i].state = (UInt8)saveStateGet(state, tag, 0);
465
466 sprintf(tag, "substate%d", i);
467 pslot[i].substate = (UInt8)saveStateGet(state, tag, 0);
468
469 sprintf(tag, "sslReg%d", i);
470 pslot[i].sslReg = (UInt8)saveStateGet(state, tag, 0);
471 }
472
473 saveStateClose(state);
474
475 for (page = 0; page < 4; page++) {
476 int psl = pslot[page].state;
477 int ssl = pslot[psl].subslotted ? pslot[page].substate : 0;
478
479 slotMapRamPage(psl, ssl, 2 * page);
480 slotMapRamPage(psl, ssl, 2 * page + 1);
481 }
482 }
483