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