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