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