1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/Memory/ramMapper.c,v $
3 **
4 ** $Revision: 1.21 $
5 **
6 ** $Date: 2009-07-03 21:27:14 $
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 "ramMapper.h"
29 #include "romMapperDRAM.h"
30 #include "ramMapperIo.h"
31 #include "MediaDb.h"
32 #include "SlotManager.h"
33 #include "DeviceManager.h"
34 #include "DebugDeviceManager.h"
35 #include "SaveState.h"
36 #include "IoPort.h"
37 #include "Language.h"
38 #include <stdlib.h>
39 #include <string.h>
40 #include <stdio.h>
41
42
43 typedef struct {
44 int deviceHandle;
45 UInt8* ramData;
46 int handle;
47 int debugHandle;
48 int dramHandle;
49 int dramMode;
50 UInt8 port[4];
51 int slot;
52 int sslot;
53 int mask;
54 int size;
55 } RamMapper;
56
57 static void writeIo(RamMapper* rm, UInt16 page, UInt8 value);
58
saveState(RamMapper * rm)59 static void saveState(RamMapper* rm)
60 {
61 SaveState* state = saveStateOpenForWrite("mapperRam");
62
63 saveStateSet(state, "mask", rm->mask);
64 saveStateSet(state, "dramMode", rm->dramMode);
65
66 saveStateSetBuffer(state, "port", rm->port, 4);
67 saveStateSetBuffer(state, "ramData", rm->ramData, 0x4000 * (rm->mask + 1));
68
69 saveStateClose(state);
70 }
71
loadState(RamMapper * rm)72 static void loadState(RamMapper* rm)
73 {
74 SaveState* state = saveStateOpenForRead("mapperRam");
75 int i;
76
77 rm->mask = saveStateGet(state, "mask", 0);
78 rm->dramMode = saveStateGet(state, "dramMode", 0);
79
80 saveStateGetBuffer(state, "port", rm->port, 4);
81 saveStateGetBuffer(state, "ramData", rm->ramData, 0x4000 * (rm->mask + 1));
82
83 saveStateClose(state);
84
85 #if 1
86 for (i = 0; i < 4; i++) {
87 writeIo(rm, i, rm->port[i]);
88 }
89 #else
90 ramMapperIoRemove(rm->handle);
91 rm->handle = ramMapperIoAdd(0x4000 * (rm->mask + 1), writeIo, rm);
92
93 for (i = 0; i < 4; i++) {
94 int value = ramMapperIoGetPortValue(i) & rm->mask;
95 int mapped = rm->dramMode && (rm->mask - value < 4) ? 0 : 1;
96 slotMapPage(rm->slot, rm->sslot, 2 * i, rm->ramData + 0x4000 * value, 1, mapped);
97 slotMapPage(rm->slot, rm->sslot, 2 * i + 1, rm->ramData + 0x4000 * value + 0x2000, 1, mapped);
98 }
99 #endif
100 }
101
writeIo(RamMapper * rm,UInt16 page,UInt8 value)102 static void writeIo(RamMapper* rm, UInt16 page, UInt8 value)
103 {
104 int baseAddr = 0x4000 * (value & rm->mask);
105 rm->port[page] = value;
106 if (rm->dramMode && baseAddr >= (rm->size - 0x10000)) {
107 slotMapPage(rm->slot, rm->sslot, 2 * page, NULL, 0, 0);
108 slotMapPage(rm->slot, rm->sslot, 2 * page + 1, NULL, 0, 0);
109 }
110 else {
111 slotMapPage(rm->slot, rm->sslot, 2 * page, rm->ramData + baseAddr, 1, 1);
112 slotMapPage(rm->slot, rm->sslot, 2 * page + 1, rm->ramData + baseAddr + 0x2000, 1, 1);
113 }
114 }
115
setDram(RamMapper * rm,int enable)116 static void setDram(RamMapper* rm, int enable)
117 {
118 int i;
119
120 rm->dramMode = enable;
121
122 for (i = 0; i < 4; i++) {
123 writeIo(rm, i, ramMapperIoGetPortValue(i));
124 }
125 }
126
reset(RamMapper * rm)127 static void reset(RamMapper* rm)
128 {
129 setDram(rm, 0);
130 }
131
destroy(RamMapper * rm)132 static void destroy(RamMapper* rm)
133 {
134 debugDeviceUnregister(rm->debugHandle);
135 ramMapperIoRemove(rm->handle);
136 slotUnregister(rm->slot, rm->sslot, 0);
137 deviceManagerUnregister(rm->deviceHandle);
138 panasonicDramUnregister(rm->dramHandle);
139 free(rm->ramData);
140
141 free(rm);
142 }
143
getDebugInfo(RamMapper * rm,DbgDevice * dbgDevice)144 static void getDebugInfo(RamMapper* rm, DbgDevice* dbgDevice)
145 {
146 dbgDeviceAddMemoryBlock(dbgDevice, langDbgMemRamMapped(), 0, 0, rm->size, rm->ramData);
147 }
148
dbgWriteMemory(RamMapper * rm,char * name,void * data,int start,int size)149 static int dbgWriteMemory(RamMapper* rm, char* name, void* data, int start, int size)
150 {
151 if (strcmp(name, "Mapped") || start + size > rm->size) {
152 return 0;
153 }
154
155 memcpy(rm->ramData + start, data, size);
156
157 return 1;
158 }
159
ramMapperCreate(int size,int slot,int sslot,int startPage,UInt8 ** ramPtr,UInt32 * ramSize)160 int ramMapperCreate(int size, int slot, int sslot, int startPage, UInt8** ramPtr, UInt32* ramSize)
161 {
162 DeviceCallbacks callbacks = { destroy, NULL, saveState, loadState };
163 DebugCallbacks dbgCallbacks = { getDebugInfo, dbgWriteMemory, NULL, NULL };
164 RamMapper* rm;
165 int pages = size / 0x4000;
166 int i;
167
168 // Check that memory is a power of 2 and at least 64kB
169 for (i = 4; i < pages; i <<= 1);
170
171 if (i != pages) {
172 return 0;
173 }
174
175 size = pages * 0x4000;
176
177 // Start page must be zero (only full slot allowed)
178 if (startPage != 0) {
179 return 0;
180 }
181
182 rm = malloc(sizeof(RamMapper));
183
184 rm->ramData = malloc(size);
185 rm->size = size;
186 rm->slot = slot;
187 rm->sslot = sslot;
188 rm->mask = pages - 1;
189 rm->dramMode = 0;
190
191 memset(rm->ramData, 0xff, size);
192
193 rm->handle = ramMapperIoAdd(pages * 0x4000, writeIo, rm);
194
195 rm->debugHandle = debugDeviceRegister(DBGTYPE_RAM, langDbgDevRam(), &dbgCallbacks, rm);
196
197 rm->deviceHandle = deviceManagerRegister(RAM_MAPPER, &callbacks, rm);
198 slotRegister(slot, sslot, 0, 8, NULL, NULL, NULL, destroy, rm);
199
200 reset(rm);
201
202 if (ramPtr != NULL) {
203 // Main RAM
204 rm->dramHandle = panasonicDramRegister(setDram, rm);
205 *ramPtr = rm->ramData;
206 }
207 if (ramSize != NULL) {
208 *ramSize = size;
209 }
210
211 return 1;
212 }
213
214