1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/Memory/romMapperNational.c,v $
3 **
4 ** $Revision: 1.6 $
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 "romMapperNational.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 sram[0x1000];
43 char sramFilename[512];
44 int slot;
45 int sslot;
46 int size;
47 int control;
48 int sramAddr;
49 int romMapper[8];
50 } RomMapperNational;
51
saveState(RomMapperNational * rm)52 static void saveState(RomMapperNational* rm)
53 {
54 SaveState* state = saveStateOpenForWrite("mapperNational");
55 char tag[16];
56 int i;
57
58 for (i = 0; i < 8; i++) {
59 sprintf(tag, "romMapper%d", i);
60 saveStateSet(state, tag, rm->romMapper[i]);
61 }
62
63 saveStateSet(state, "control", rm->control);
64 saveStateSet(state, "sramAddr", rm->sramAddr);
65
66 saveStateClose(state);
67 }
68
loadState(RomMapperNational * rm)69 static void loadState(RomMapperNational* rm)
70 {
71 SaveState* state = saveStateOpenForRead("mapperNational");
72 char tag[16];
73 int i;
74
75 for (i = 0; i < 8; i++) {
76 sprintf(tag, "romMapper%d", i);
77 rm->romMapper[i] = saveStateGet(state, tag, 0);
78 }
79
80 rm->control = saveStateGet(state, "control", 0);
81 rm->sramAddr = saveStateGet(state, "sramAddr", 0);
82
83 saveStateClose(state);
84
85 for (i = 0; i < 8; i += 2) {
86 slotMapPage(rm->slot, rm->sslot, i, rm->romData + rm->romMapper[i] * 0x4000, 1, 0);
87 }
88 }
89
destroy(RomMapperNational * rm)90 static void destroy(RomMapperNational* rm)
91 {
92 sramSave(rm->sramFilename, rm->sram, 0x800, NULL, 0);
93
94 slotUnregister(rm->slot, rm->sslot, 0);
95 deviceManagerUnregister(rm->deviceHandle);
96
97 free(rm->romData);
98 free(rm);
99 }
100
read(RomMapperNational * rm,UInt16 address)101 static UInt8 read(RomMapperNational* rm, UInt16 address)
102 {
103 if ((rm->control & 0x04) && (address & 0x7ff9) == 0x7ff0) {
104 return rm->romMapper[address & 0x06];
105 }
106
107 if ((rm->control & 0x02) && ((address & 0x3fff) == 0x3ffd)) {
108 return rm->sram[rm->sramAddr++ & 0x0fff];
109 }
110
111 return rm->romData[(rm->romMapper[(address >> 13) & ~1] << 14) + (address & 0x3fff)];
112 }
113
peek(RomMapperNational * rm,UInt16 address)114 static UInt8 peek(RomMapperNational* rm, UInt16 address)
115 {
116 if ((rm->control & 0x04) && (address & 0x7ff9) == 0x7ff0) {
117 return rm->romMapper[address & 0x06];
118 }
119
120 if ((rm->control & 0x02) && ((address & 0x3fff) == 0x3ffd)) {
121 return rm->sram[rm->sramAddr & 0x0fff];
122 }
123
124 return rm->romData[(rm->romMapper[(address >> 13) & ~1] << 14) + (address & 0x3fff)];
125 }
126
write(RomMapperNational * rm,UInt16 address,UInt8 value)127 static void write(RomMapperNational* rm, UInt16 address, UInt8 value)
128 {
129 if (address == 0x6000) {
130 rm->romMapper[2] = value;
131 slotMapPage(rm->slot, rm->sslot, 2, rm->romData + ((int)value << 14), 1, 0);
132 }
133 else if (address == 0x6400) {
134 rm->romMapper[0] = value;
135 slotMapPage(rm->slot, rm->sslot, 0, rm->romData + ((int)value << 14), 1, 0);
136 }
137 else if (address == 0x7000) {
138 rm->romMapper[4] = value;
139 slotMapPage(rm->slot, rm->sslot, 4, rm->romData + ((int)value << 14), 1, 0);
140 }
141 else if (address == 0x7400) {
142 rm->romMapper[6] = value;
143 slotMapPage(rm->slot, rm->sslot, 6, rm->romData + ((int)value << 14), 1, 0);
144 }
145 else if (address == 0x7ff9) {
146 rm->control = value;
147 }
148 else if (rm->control & 0x02) {
149 address &= 0x3fff;
150 if (address == 0x3ffa) {
151 rm->sramAddr = (rm->sramAddr & 0x00fff) | value << 16;
152 }
153 else if (address == 0x3ffb) {
154 rm->sramAddr = (rm->sramAddr & 0xff00ff) | value << 8;
155 }
156 else if (address == 0x3ffc) {
157 rm->sramAddr = (rm->sramAddr & 0xffff00) | value;
158 }
159 else if (address == 0x3ffd) {
160 rm->sram[rm->sramAddr++ & 0x0fff] = value;
161 }
162 }
163 }
164
romMapperNationalCreate(const char * filename,UInt8 * romData,int size,int slot,int sslot,int startPage)165 int romMapperNationalCreate(const char* filename, UInt8* romData,
166 int size, int slot, int sslot, int startPage)
167 {
168 DeviceCallbacks callbacks = { destroy, NULL, saveState, loadState };
169 RomMapperNational* rm;
170 int i;
171
172 if (size < 0x8000 || startPage != 0) {
173 return 0;
174 }
175
176 rm = malloc(sizeof(RomMapperNational));
177
178 rm->deviceHandle = deviceManagerRegister(ROM_NATIONAL, &callbacks, rm);
179 slotRegister(slot, sslot, 0, 8, read, peek, write, destroy, rm);
180
181 rm->romData = malloc(size);
182 memcpy(rm->romData, romData, size);
183 memset(rm->sram, 0xff, 0x1000);
184 rm->size = size;
185 rm->sramAddr = 0;
186 rm->control = 0;
187 rm->slot = slot;
188 rm->sslot = sslot;
189 strcpy(rm->sramFilename, sramCreateFilename(filename));
190
191 sramLoad(rm->sramFilename, rm->sram, 0x1000, NULL, 0);
192
193 rm->romMapper[0] = 0;
194 rm->romMapper[2] = 0;
195 rm->romMapper[4] = 0;
196 rm->romMapper[6] = 0;
197
198 for (i = 0; i < 8; i += 2) {
199 slotMapPage(slot, sslot, i, rm->romData + rm->romMapper[i] * 0x2000, 1, 0 );
200 slotMapPage(slot, sslot, i + 1, rm->romData + rm->romMapper[i] * 0x2000 + 0x2000, 0, 0);
201 }
202
203 return 1;
204 }
205
206