1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/Memory/romMapperMuPack.c,v $
3 **
4 ** $Revision: 1.10 $
5 **
6 ** $Date: 2008-03-30 18:38:44 $
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 "romMapperMuPack.h"
29 #include "MediaDb.h"
30 #include "SlotManager.h"
31 #include "DeviceManager.h"
32 #include "SaveState.h"
33 #include "ramMapperIo.h"
34 #include "MSXMidi.h"
35 #include <stdlib.h>
36 #include <string.h>
37 
38 
39 typedef struct {
40     int deviceHandle;
41     UInt8* romData;
42     int slot;
43     int sslot;
44     int romSize;
45     UInt8 sslReg;
46     UInt8 subslot[4];
47 
48     int handle;
49     UInt8* ramData;
50     int ramMask;
51     UInt8 ramPort[4];
52 
53 } RomMapperMuPack;
54 
55 
writeIo(RomMapperMuPack * rm,UInt16 page,UInt8 value)56 static void writeIo(RomMapperMuPack* rm, UInt16 page, UInt8 value)
57 {
58     rm->ramPort[page] = value;
59 }
60 
saveState(RomMapperMuPack * rm)61 static void saveState(RomMapperMuPack* rm)
62 {
63     SaveState* state = saveStateOpenForWrite("mapperMuPack");
64 
65     saveStateSet(state, "sslReg", rm->sslReg);
66     saveStateSetBuffer(state, "subslot", rm->subslot, 4);
67 
68     saveStateSetBuffer(state, "ramPort", rm->ramPort, 4);
69     saveStateSetBuffer(state, "ramData", rm->ramData, 0x4000 * (rm->ramMask + 1));
70 
71     saveStateClose(state);
72 }
73 
loadState(RomMapperMuPack * rm)74 static void loadState(RomMapperMuPack* rm)
75 {
76     SaveState* state = saveStateOpenForRead("mapperMuPack");
77     int i;
78 
79     rm->sslReg = (UInt8)saveStateGet(state, "sslReg", 0);
80     saveStateGetBuffer(state, "subslot", rm->subslot, 4);
81 
82     saveStateGetBuffer(state, "ramPort", rm->ramPort, 4);
83     saveStateGetBuffer(state, "ramData", rm->ramData, 0x4000 * (rm->ramMask + 1));
84 
85     saveStateClose(state);
86 
87     for (i = 0; i < 4; i++) {
88         writeIo(rm, i, rm->ramPort[i]);
89     }
90 }
91 
destroy(RomMapperMuPack * rm)92 static void destroy(RomMapperMuPack* rm)
93 {
94     slotUnregister(rm->slot, rm->sslot, 0);
95     deviceManagerUnregister(rm->deviceHandle);
96 
97     ramMapperIoRemove(rm->handle);
98 
99     free(rm->romData);
100     free(rm->ramData);
101     free(rm);
102 }
103 
reset(RomMapperMuPack * rm)104 static void reset(RomMapperMuPack* rm)
105 {
106     int page;
107     rm->sslReg = 0;
108     for (page = 0; page < 4; page++) {
109         rm->subslot[page] = 0;
110         rm->ramPort[page] = page;
111     }
112 }
113 
read(RomMapperMuPack * rm,UInt16 address)114 static UInt8 read(RomMapperMuPack* rm, UInt16 address)
115 {
116     int page = address >> 14;
117     int ramBaseAddr;
118 
119     if (address == 0xffff) {
120         return ~rm->sslReg;
121     }
122 
123     switch (rm->subslot[page]) {
124     case 1:
125         ramBaseAddr = 0x4000 * (rm->ramPort[page] & rm->ramMask);
126         return rm->ramData[ramBaseAddr + (address & 0x3fff)];
127     case 2:
128         if (address >= 0x4000 && address < 0x4000 + rm->romSize) {
129             return rm->romData[address - 0x4000];
130         }
131         return 0xff;
132     }
133     return 0xff;
134 }
135 
136 
write(RomMapperMuPack * rm,UInt16 address,UInt8 value)137 static void write(RomMapperMuPack* rm, UInt16 address, UInt8 value)
138 {
139     int page = address >> 14;
140     int ramBaseAddr;
141 
142     if (address == 0xffff) {
143         rm->sslReg = value;
144         for (page = 0; page < 4; page++) {
145             rm->subslot[page] = value & 3;
146             value >>= 2;
147         }
148         return;
149     }
150     switch (rm->subslot[page]) {
151     case 1:
152         ramBaseAddr = 0x4000 * (rm->ramPort[page] & rm->ramMask);
153         rm->ramData[ramBaseAddr + (address & 0x3fff)] = value;
154     }
155 }
156 
romMapperMuPackCreate(const char * filename,UInt8 * romData,int size,int slot,int sslot,int startPage)157 int romMapperMuPackCreate(const char* filename, UInt8* romData,
158                            int size, int slot, int sslot, int startPage)
159 {
160     DeviceCallbacks callbacks = { destroy, reset, saveState, loadState };
161     RomMapperMuPack* rm;
162     int i;
163 
164     rm = malloc(sizeof(RomMapperMuPack));
165 
166     rm->deviceHandle = deviceManagerRegister(ROM_MUPACK, &callbacks, rm);
167     slotRegister(slot, sslot, 0, 8, read, read, write, destroy, rm);
168 
169     rm->romData = calloc(1, size);
170     memcpy(rm->romData, romData, size);
171     rm->romSize = size;
172     rm->slot  = slot;
173     rm->sslot = sslot;
174 
175     // Ram mapper
176     rm->ramMask = 16 - 1;
177     rm->ramData  = malloc((rm->ramMask + 1) * 0x4000);
178     rm->handle  = ramMapperIoAdd((rm->ramMask + 1) * 0x4000, writeIo, rm);
179 
180     // MIDI
181     MSXMidiCreate(1);
182 
183     for (i = 0; i < 8; i++) {
184         slotMapPage(rm->slot, rm->sslot, i, NULL, 0, 0);
185     }
186 
187     reset(rm);
188 
189     return 1;
190 }
191 
192