1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/Memory/ram1kBMirrored.c,v $
3 **
4 ** $Revision: 1.12 $
5 **
6 ** $Date: 2008-05-19 19:25:59 $
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 "ram1kBMirrored.h"
29 #include "MediaDb.h"
30 #include "SlotManager.h"
31 #include "DeviceManager.h"
32 #include "DebugDeviceManager.h"
33 #include "SaveState.h"
34 #include "Language.h"
35 #include <stdlib.h>
36 #include <string.h>
37 #include <stdio.h>
38 
39 
40 typedef struct {
41     int deviceHandle;
42     int debugHandle;
43     int slot;
44     int sslot;
45     int startPage;
46     int pages;
47     UInt32 mask;
48     UInt8 ramData[0x2000];
49 } Ram1kBMirrored;
50 
saveState(Ram1kBMirrored * rm)51 static void saveState(Ram1kBMirrored* rm)
52 {
53     SaveState* state = saveStateOpenForWrite("mapperMirroredRam");
54 
55     saveStateSet(state, "mask", rm->mask);
56     saveStateSetBuffer(state, "ramData", rm->ramData, rm->mask + 1);
57 
58     saveStateClose(state);
59 }
60 
loadState(Ram1kBMirrored * rm)61 static void loadState(Ram1kBMirrored* rm)
62 {
63     SaveState* state = saveStateOpenForRead("mapperMirroredRam");
64 
65     rm->mask = saveStateGet(state, "mask", 0x400);
66     saveStateGetBuffer(state, "ramData", rm->ramData, rm->mask + 1);
67 
68     saveStateClose(state);
69 }
70 
destroy(Ram1kBMirrored * rm)71 static void destroy(Ram1kBMirrored* rm)
72 {
73     debugDeviceUnregister(rm->debugHandle);
74 
75     slotUnregister(rm->slot, rm->sslot, 0);
76     deviceManagerUnregister(rm->deviceHandle);
77 
78     free(rm);
79 }
80 
getDebugInfo(Ram1kBMirrored * rm,DbgDevice * dbgDevice)81 static void getDebugInfo(Ram1kBMirrored* rm, DbgDevice* dbgDevice)
82 {
83     dbgDeviceAddMemoryBlock(dbgDevice, langDbgMemRamNormal(), 0, 0, rm->mask + 1, rm->ramData);
84 }
85 
dbgWriteMemory(Ram1kBMirrored * rm,char * name,void * data,int start,int size)86 static int dbgWriteMemory(Ram1kBMirrored* rm, char* name, void* data, int start, int size)
87 {
88     if (strcmp(name, "Normal") || start + size >= (int)rm->mask) {
89         return 0;
90     }
91 
92     memcpy(rm->ramData + start, data, size);
93 
94     return 1;
95 }
96 
read(Ram1kBMirrored * rm,UInt16 address)97 static UInt8 read(Ram1kBMirrored* rm, UInt16 address)
98 {
99     return rm->ramData[address & rm->mask];
100 }
101 
write(Ram1kBMirrored * rm,UInt16 address,UInt8 value)102 static void write(Ram1kBMirrored* rm, UInt16 address, UInt8 value)
103 {
104     rm->ramData[address & rm->mask] = value;
105 }
106 
ramMirroredCreate(int size,int slot,int sslot,int startPage,UInt32 ramBlockSize,UInt8 ** ramPtr,UInt32 * ramSize)107 int ramMirroredCreate(int size, int slot, int sslot, int startPage,
108                       UInt32 ramBlockSize, UInt8** ramPtr, UInt32* ramSize)
109 {
110     DeviceCallbacks callbacks = { destroy, NULL, saveState, loadState };
111     DebugCallbacks dbgCallbacks = { getDebugInfo, dbgWriteMemory, NULL, NULL };
112     Ram1kBMirrored* rm;
113     int pages = size / 0x2000;
114     int i;
115 
116     if (size > 0x10000 || (size & 0x1fff)) {
117         return 0;
118     }
119 
120     // Start page must be zero (only full slot allowed)
121     if (startPage + pages > 8) {
122         return 0;
123     }
124 
125     rm = malloc(sizeof(Ram1kBMirrored));
126 
127     rm->mask      = ramBlockSize - 1;
128     rm->slot      = slot;
129     rm->sslot     = sslot;
130     rm->startPage = startPage;
131     rm->pages     = pages;
132 
133     memset(rm->ramData, 0, sizeof(rm->ramData));
134 
135     rm->debugHandle = debugDeviceRegister(DBGTYPE_RAM, langDbgDevRam(), &dbgCallbacks, rm);
136 
137     for (i = 0; i < pages; i++) {
138         slotMapPage(slot, sslot, i + startPage, NULL, 0, 0);
139     }
140 
141     rm->deviceHandle = deviceManagerRegister(ramBlockSize == 0x400 ? RAM_1KB_MIRRORED : RAM_2KB_MIRRORED,
142                                              &callbacks, rm);
143     slotRegister(slot, sslot, startPage, pages, read, read, write, destroy, rm);
144 
145     if (ramPtr != NULL) {
146         *ramPtr = rm->ramData;
147     }
148 
149     if (ramSize != NULL) {
150         *ramSize = rm->pages * 0x2000;
151     }
152 
153     return 1;
154 }
155 
156