1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/Memory/ramMapperIo.c,v $
3 **
4 ** $Revision: 1.9 $
5 **
6 ** $Date: 2008-03-30 18:38:42 $
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 "ramMapperIo.h"
29 #include "MediaDb.h"
30 #include "DeviceManager.h"
31 #include "DebugDeviceManager.h"
32 #include "SaveState.h"
33 #include "Language.h"
34 #include "IoPort.h"
35 #include <stdlib.h>
36 #include <string.h>
37 #include <stdio.h>
38 
39 
40 typedef struct {
41     int        handle;
42     MemIoWrite write;
43     void*      ref;
44     int        size;
45 } RamMapperCb;
46 
47 typedef struct {
48     int deviceHandle;
49     int debugHandle;
50     int handleCount;
51     RamMapperCb mapperCb[32];
52     int count;
53     int mask;
54     int port[4];
55 } RamMapperIo;
56 
57 RamMapperIo* mapperIo = NULL;
58 
59 
ramMapperIoGetMask(RamMapperIo * rm)60 static int ramMapperIoGetMask(RamMapperIo* rm)
61 {
62     int size = 1;
63     int i;
64 
65     for (i = 0; i < rm->count; i++) {
66         while (size < rm->mapperCb[i].size) {
67             size <<= 1;
68         }
69     }
70 
71     return (size / 0x4000) - 1;
72 }
73 
saveState(RamMapperIo * rm)74 static void saveState(RamMapperIo* rm)
75 {
76     SaveState* state = saveStateOpenForWrite("mapperRamIo");
77     saveStateSet(state, "port0", rm->port[0]);
78     saveStateSet(state, "port1", rm->port[1]);
79     saveStateSet(state, "port2", rm->port[2]);
80     saveStateSet(state, "port3", rm->port[3]);
81 
82     saveStateClose(state);
83 }
84 
loadState(RamMapperIo * rm)85 static void loadState(RamMapperIo* rm)
86 {
87     SaveState* state = saveStateOpenForRead("mapperRamIo");
88     rm->port[0] = saveStateGet(state, "port0", 3);
89     rm->port[1] = saveStateGet(state, "port1", 2);
90     rm->port[2] = saveStateGet(state, "port2", 1);
91     rm->port[3] = saveStateGet(state, "port3", 0);
92 
93     rm->mask = ramMapperIoGetMask(rm);
94 
95     saveStateClose(state);
96 }
97 
destroy(RamMapperIo * rm)98 static void destroy(RamMapperIo* rm)
99 {
100     ioPortUnregister(0xfc);
101     ioPortUnregister(0xfd);
102     ioPortUnregister(0xfe);
103     ioPortUnregister(0xff);
104 
105     deviceManagerUnregister(rm->deviceHandle);
106     debugDeviceUnregister(rm->debugHandle);
107 
108     free(mapperIo);
109     mapperIo = NULL;
110 }
111 
read(RamMapperIo * rm,UInt16 ioPort)112 static UInt8 read(RamMapperIo* rm, UInt16 ioPort)
113 {
114     return rm->port[ioPort & 3] | ~rm->mask;
115 }
116 
write(RamMapperIo * rm,UInt16 ioPort,UInt8 value)117 static void write(RamMapperIo* rm, UInt16 ioPort, UInt8 value)
118 {
119     ioPort &= 3;
120 
121     if (rm->port[ioPort] != value) {
122         int i;
123 
124         rm->port[ioPort] = value;
125 
126         for (i = 0; i < rm->count; i++) {
127             if (rm->mapperCb[i].write != NULL) {
128                 rm->mapperCb[i].write(rm->mapperCb[i].ref, ioPort, value);
129             }
130         }
131     }
132 }
133 
getDebugInfo(RamMapperIo * rm,DbgDevice * dbgDevice)134 static void getDebugInfo(RamMapperIo* rm, DbgDevice* dbgDevice)
135 {
136     DbgIoPorts* ioPorts;
137     int i;
138 
139     ioPorts = dbgDeviceAddIoPorts(dbgDevice, langDbgDevRamMapper(), 4);
140     for (i = 0; i < 4; i++) {
141         dbgIoPortsAddPort(ioPorts, i, 0xfc + i, DBG_IO_READWRITE, read(rm, 0xfc + i));
142     }
143 }
144 
ramMapperIoCreate()145 int ramMapperIoCreate()
146 {
147     RamMapperIo* rm;
148     DeviceCallbacks callbacks = { destroy, NULL, saveState, loadState };
149     DebugCallbacks dbgCallbacks = { getDebugInfo, NULL, NULL, NULL };
150 
151     rm = malloc(sizeof(RamMapperIo));
152     rm->count = 0;
153     rm->mask  = 0;
154     rm->handleCount = 0;
155 
156     rm->port[0] = 3;
157     rm->port[1] = 2;
158     rm->port[2] = 1;
159     rm->port[3] = 0;
160 
161     rm->deviceHandle = deviceManagerRegister(RAM_MAPPER, &callbacks, rm);
162     rm->debugHandle = debugDeviceRegister(DBGTYPE_BIOS, langDbgDevRamMapper(), &dbgCallbacks, rm);
163 
164     ioPortRegister(0xfc, read, write, rm);
165     ioPortRegister(0xfd, read, write, rm);
166     ioPortRegister(0xfe, read, write, rm);
167     ioPortRegister(0xff, read, write, rm);
168 
169     mapperIo = rm;
170 
171     return 1;
172 }
173 
ramMapperIoGetPortValue(int ioPort)174 int ramMapperIoGetPortValue(int ioPort)
175 {
176     RamMapperIo* rm = mapperIo;
177     if (rm == NULL) {
178         return 0xff;
179     }
180 
181     return rm->port[ioPort & 3];
182 }
183 
ramMapperIoAdd(int size,MemIoWrite write,void * ref)184 int ramMapperIoAdd(int size, MemIoWrite write, void* ref)
185 {
186     RamMapperIo* rm = mapperIo;
187     RamMapperCb mapperCb = { ++rm->handleCount, write, ref, size };
188 
189     if (rm == NULL || rm->count == 32) {
190         return 0;
191     }
192 
193     rm->mapperCb[rm->count++] = mapperCb;
194 
195     rm->mask = ramMapperIoGetMask(rm);
196 
197     return rm->handleCount;
198 }
199 
ramMapperIoRemove(int handle)200 void ramMapperIoRemove(int handle)
201 {
202     RamMapperIo* rm = mapperIo;
203     int i;
204 
205     if (rm == NULL || rm->count == 0) {
206         return;
207     }
208 
209     for (i = 0; i < rm->count; i++) {
210         if (rm->mapperCb[i].handle == handle) {
211             break;
212         }
213     }
214 
215     if (i == rm->count) {
216         return;
217     }
218 
219     rm->count--;
220     while (i < rm->count) {
221         rm->mapperCb[i] = rm->mapperCb[i + 1];
222         i++;
223     }
224 
225     rm->mask = ramMapperIoGetMask(rm);
226 }
227