1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/Memory/romMapperSg1000RamExpander.c,v $
3 **
4 ** $Revision: 1.5 $
5 **
6 ** $Date: 2008-03-30 18:38:44 $
7 **
8 ** More info: http://www.bluemsx.com
9 **
10 ** Copyright (C) 2003-2012 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 "romMapperSg1000RamExpander.h"
29 #include "MediaDb.h"
30 #include "SlotManager.h"
31 #include "DeviceManager.h"
32 #include "SaveState.h"
33 #include "sramLoader.h"
34 #include <stdlib.h>
35 #include <string.h>
36 #include <stdio.h>
37 
38 
39 typedef struct {
40     int deviceHandle;
41     UInt8* romData;
42     UInt8 ram1[0x2000];
43     UInt8 ram2[0x2000];
44     int slot;
45     int sslot;
46     int startPage;
47     int mask2;
48 } RomMapperSg1000RamExpander;
49 
saveState(RomMapperSg1000RamExpander * rm)50 static void saveState(RomMapperSg1000RamExpander* rm)
51 {
52     SaveState* state = saveStateOpenForWrite("mapperSegaRamExpander");
53 
54     saveStateSet(state, "mask2", rm->mask2);
55     saveStateSetBuffer(state, "ram1", rm->ram1, 0x2000);
56     saveStateSetBuffer(state, "ram2", rm->ram2, rm->mask2 + 1);
57 
58     saveStateClose(state);
59 }
60 
loadState(RomMapperSg1000RamExpander * rm)61 static void loadState(RomMapperSg1000RamExpander* rm)
62 {
63     SaveState* state = saveStateOpenForRead("mapperSegaRamExpander");
64 
65     rm->mask2 = saveStateGet(state, "mask2", 0x400);
66     saveStateGetBuffer(state, "ram1", rm->ram2, 0x2000);
67     saveStateGetBuffer(state, "ram2", rm->ram2, rm->mask2 + 1);
68 
69     saveStateClose(state);
70 }
71 
destroy(RomMapperSg1000RamExpander * rm)72 static void destroy(RomMapperSg1000RamExpander* rm)
73 {
74     slotUnregister(rm->slot, rm->sslot, rm->startPage);
75     deviceManagerUnregister(rm->deviceHandle);
76 
77     free(rm->romData);
78     free(rm);
79 }
80 
read(RomMapperSg1000RamExpander * rm,UInt16 address)81 static UInt8 read(RomMapperSg1000RamExpander* rm, UInt16 address)
82 {
83     return rm->ram2[address & rm->mask2];
84 }
85 
write(RomMapperSg1000RamExpander * rm,UInt16 address,UInt8 value)86 static void write(RomMapperSg1000RamExpander* rm, UInt16 address, UInt8 value)
87 {
88     rm->ram2[address & rm->mask2] = value;
89 }
90 
romMapperSg1000RamExpanderCreate(const char * filename,UInt8 * romData,int size,int slot,int sslot,int startPage,int type)91 int romMapperSg1000RamExpanderCreate(const char* filename, UInt8* romData,
92                                      int size, int slot, int sslot, int startPage, int type)
93 {
94     DeviceCallbacks callbacks = { destroy, NULL, saveState, loadState };
95     RomMapperSg1000RamExpander* rm;
96     int pages = size / 0x2000 + ((size & 0x1fff) ? 1 : 0);
97     int i;
98 
99     if (size != 0x8000 || startPage != 0) {
100         return 0;
101     }
102 
103     rm = malloc(sizeof(RomMapperSg1000RamExpander));
104 
105     rm->deviceHandle = deviceManagerRegister(type, &callbacks, rm);
106     slotRegister(slot, sslot, startPage, pages, read, read, write, destroy, rm);
107 
108     rm->romData = malloc(pages * 0x2000);
109     memcpy(rm->romData, romData, size);
110     memset(rm->ram1, sizeof(rm->ram1), 0xff);
111     memset(rm->ram2, sizeof(rm->ram2), 0xff);
112 
113     rm->slot  = slot;
114     rm->sslot = sslot;
115     rm->startPage  = startPage;
116     rm->mask2 = ROM_SG1000_RAMEXPANDER_A ? 0x0400 : 0x2000;
117 
118     for (i = 0; i < pages; i++) {
119         if (i + startPage >= 2) slot = 0;
120         if (type == ROM_SG1000_RAMEXPANDER_A && i + startPage == 1) {
121             slotMapPage(slot, sslot, i + startPage, rm->ram1, 1, 1);
122         }
123         else {
124             slotMapPage(slot, sslot, i + startPage, rm->romData + 0x2000 * i, 1, 0);
125         }
126     }
127 
128     slotMapPage(slot, sslot, 6, NULL, 0, 0);
129     slotMapPage(slot, sslot, 7, NULL, 0, 0);
130 
131     return 1;
132 }
133 
134