OSDN Git Service

[VM][FMTOWNS][MEMORY] Fix setup around memory banks by I/O 0404h and 0480h.
[csp-qt/common_source_project-fm7.git] / source / src / vm / msx / memory_ex.cpp
1 /*
2         Common Source Code Project
3         MSX Series (experimental)
4
5         Origin : src/vm/msx/memory.cpp
6
7         modified by umaiboux
8         Date   : 2016.03.xx-
9
10         [ memory ]
11 */
12
13 #include "memory_ex.h"
14 #if defined(LDC_SLOT)
15 #include "../ld700.h"
16 #include "../tms9918a.h"
17 #endif
18 #if defined(FDD_PATCH_SLOT)
19 #include "../disk.h"
20 #if defined(MSX_FDD_PATCH_WITH_2HD)
21 #define MSX_SECTOR_SIZE (disk[drv]->sector_size.sd)
22 #else
23 #define MSX_SECTOR_SIZE 512
24 #endif
25 #endif
26 #if defined(FDD_PATCH_SLOT) && defined(_MSX_VDP_MESS)
27 #include "../v9938.h"
28 #endif
29
30 #ifdef USE_MEGAROM
31 //#include "scc.h"
32 #include "romtype1.h"
33
34 #define EVENT_ROMTYPE   1
35 #define ROMTYPE_NONE    (-1)
36 static struct s_typestr {
37         int type;
38         const _TCHAR *p;
39 } typestr[] = {
40         {ROM_ASCII8,            _T("ASCII8")},
41         {ROM_ASCII16,           _T("ASCII16")},
42         {ROM_KONAMI,            _T("KONAMI")},
43         {ROM_KONAMI_SCC,        _T("KONAMI_SCC")},
44         {ROMTYPE_NONE,          _T("NONE")}
45 };
46
47 #include "romtype2.h"
48 #endif
49
50 #define EVENT_CLOCK     0
51
52 namespace MSX {
53         
54 #define SET_BANK(s, e, w, r) { \
55         int sb = (s) >> 13, eb = (e) >> 13; \
56         for(int i = sb; i <= eb; i++) { \
57                 if(((uintptr_t)w) == ((uintptr_t)wdmy)) {       \
58                         wbank[i] = wdmy; \
59                 } else { \
60                         wbank[i] = (w) + 0x2000 * (i - sb); \
61                 } \
62                 if(((uintptr_t)r) == ((uintptr_t)rdmy)) {       \
63                         rbank[i] = rdmy; \
64                 } else { \
65                         rbank[i] = (r) + 0x2000 * (i - sb); \
66                 } \
67         } \
68 }
69
70 #if defined(FDD_PATCH_SLOT)
71 static const struct {
72         int sectors;
73         uint8_t heads, names, per_track, per_fat, per_cluster;
74 } info[8] = {
75         { 720,  1, 112, 9, 2, 2 },
76         { 1440, 2, 112, 9, 3, 2 },
77         { 640,  1, 112, 8, 1, 2 },
78         { 1280, 2, 112, 8, 2, 2 },
79         { 360,  1, 64,  9, 2, 1 },
80         { 720,  2, 112, 9, 2, 2 },
81         { 320,  1, 64,  8, 1, 1 },
82         { 640,  2, 112, 8, 1, 2 }
83 };
84
85 static const uint8_t boot_block[] = {
86         0xeb, 0xfe, 0x90, 0x56, 0x46, 0x42, 0x2d, 0x31, 0x39, 0x38, 0x39, 0x00, 0x02, 0x02, 0x01, 0x00,
87         0x02, 0x70, 0x00, 0xa0, 0x05, 0xf9, 0x03, 0x00, 0x09, 0x00, 0x02, 0x00, 0x00, 0x00, 0xd0, 0xed,
88         0x53, 0x58, 0xc0, 0x32, 0xc2, 0xc0, 0x36, 0x55, 0x23, 0x36, 0xc0, 0x31, 0x1f, 0xf5, 0x11, 0x9d,
89         0xc0, 0x0e, 0x0f, 0xcd, 0x7d, 0xf3, 0x3c, 0x28, 0x28, 0x11, 0x00, 0x01, 0x0e, 0x1a, 0xcd, 0x7d,
90         0xf3, 0x21, 0x01, 0x00, 0x22, 0xab, 0xc0, 0x21, 0x00, 0x3f, 0x11, 0x9d, 0xc0, 0x0e, 0x27, 0xcd,
91         0x7d, 0xf3, 0xc3, 0x00, 0x01, 0x57, 0xc0, 0xcd, 0x00, 0x00, 0x79, 0xe6, 0xfe, 0xfe, 0x02, 0x20,
92         0x07, 0x3a, 0xc2, 0xc0, 0xa7, 0xca, 0x22, 0x40, 0x11, 0x77, 0xc0, 0x0e, 0x09, 0xcd, 0x7d, 0xf3,
93         0x0e, 0x07, 0xcd, 0x7d, 0xf3, 0x18, 0xb4, 0x42, 0x6f, 0x6f, 0x74, 0x20, 0x65, 0x72, 0x72, 0x6f,
94         0x72, 0x0d, 0x0a, 0x50, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79,
95         0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x74, 0x72, 0x79, 0x0d, 0x0a, 0x24, 0x00, 0x4d, 0x53,
96         0x58, 0x44, 0x4f, 0x53, 0x20, 0x20, 0x53, 0x59, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x2a,
99         0x51, 0xf3, 0x11, 0x00, 0x01, 0x19, 0x01, 0x00, 0x01, 0x11, 0x00, 0xc1, 0xed, 0xb0, 0x3a, 0xee,
100         0xc0, 0x47, 0x11, 0xef, 0xc0, 0x21, 0x00, 0x00, 0xcd, 0x51, 0x52, 0xf3, 0x76, 0xc9, 0x18, 0x64,
101         0x3a, 0xaf, 0x80, 0xf9, 0xca, 0x6d, 0x48, 0xd3, 0xa5, 0x0c, 0x8c, 0x2f, 0x9c, 0xcb, 0xe9, 0x89,
102         0xd2, 0x00, 0x32, 0x26, 0x40, 0x94, 0x61, 0x19, 0x20, 0xe6, 0x80, 0x6d, 0x8a, 0x00, 0x00, 0x00,
103         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
118 };
119
120 static int DSKIO = -1, DSKCHG = -1, GETDPB = -1, DSKFMT = -1;
121 #endif
122
123 bool SLOT_CART::load_cart(const _TCHAR *file_path/*, uint8_t *rom*/)
124 {
125         bool result = false;
126         FILEIO* fio = new FILEIO();
127         if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
128                 memset(rom, 0xff, 0x10000);
129                 
130                 fio->Fseek(0, FILEIO_SEEK_END);
131                 uint32_t file_size = fio->Ftell();
132                 fio->Fseek(0, FILEIO_SEEK_SET);
133                 
134 #ifdef USE_MEGAROM
135                 type = ROMTYPE_NONE;
136                 SET_BANK(0x0000, 0xffff, wdmy, rom);
137                 bank_scc = false;
138                 d_sound->disable_all();
139 #endif
140                 if(file_size <= 0x2000) {
141                         // 8KB: 00000000
142                         fio->Fread(rom, 0x2000, 1);
143                         memcpy(rom + 0x2000, rom, 0x2000);
144                         memcpy(rom + 0x4000, rom, 0x4000);
145                         memcpy(rom + 0x8000, rom, 0x8000);
146                 } else if(file_size <= 0x4000) {
147                         // 16KB: 01010101
148                         fio->Fread(rom, 0x4000, 1);
149                         memcpy(rom + 0x4000, rom, 0x4000);
150                         memcpy(rom + 0x8000, rom, 0x8000);
151                 } else if(file_size <= 0x8000) {
152                         // 32KB: 01012323
153                         fio->Fread(rom + 0x4000, 0x8000, 1);
154                         memcpy(rom + 0x0000, rom + 0x4000, 0x4000);
155                         memcpy(rom + 0xc000, rom + 0x8000, 0x4000);
156                 } else {
157 #ifdef USE_MEGAROM
158                         if(file_size > 0x10000) {
159                                 if(file_size > sizeof(rom)) file_size = sizeof(rom);
160                                 fio->Fread(rom, file_size, 1);
161                                 type = hashRomType(rom, file_size);
162                                 if (ROMTYPE_NONE == type) type = guessRomType(rom, file_size);
163                                 switch(type) {
164                                 case ROM_ASCII8:
165                                 case ROM_ASCII16:
166                                 case ROM_KONAMI:
167                                 case ROM_KONAMI_SCC:
168                                         break;
169                                 default:
170                                         type = ROMTYPE_NONE;
171                                         break;
172                                 }
173                                 //register_event(this, EVENT_ROMTYPE, 1000000.0 * 5, false, NULL);
174                                 if (-1 != event_register_id) {
175                                         cancel_event(this, event_register_id);
176                                         event_register_id = -1;
177                                 }
178                                 register_event(this, EVENT_ROMTYPE, 1000000.0 * 5, true, &event_register_id);
179                                 SET_BANK(0x0000, 0x3fff, wdmy, rdmy);
180                                 SET_BANK(0xc000, 0xffff, wdmy, rdmy);
181                                 SET_BANK(0x4000, 0xbfff, wdmy, rom);
182                                 if(file_size <= 0x20000) {
183                                         memcpy(rom + 0x20000, rom, 0x20000);
184                                 }
185                                 if(file_size <= 0x40000) {
186                                         memcpy(rom + 0x40000, rom, 0x40000);
187                                 }
188                                 if(file_size <= 0x80000) {
189                                         memcpy(rom + 0x80000, rom, 0x80000);
190                                 }
191                                 if(file_size <= 0x100000) {
192                                         memcpy(rom + 0x100000, rom, 0x100000);
193                                 }
194                                 if(file_size <= 0x200000) {
195                                         memcpy(rom + 0x200000, rom, 0x200000);
196                                 }
197
198                                 if (ROM_KONAMI_SCC == type) {
199                                         d_sound->enable_c(SOUND_CHIP_SCC, true);
200                                 }
201                                 // for IKARI(ASCII 16Kb)
202                                 if (ROM_ASCII16 == type) {
203                                         SET_BANK(0x4000, 0x7fff, wdmy, rom+0x2000*(0*2));
204                                         SET_BANK(0x8000, 0xbfff, wdmy, rom+0x2000*(0*2));
205                                 }
206                         }
207                         else {
208                                 // 64KB: 01234567
209                                 fio->Fread(rom, 0x10000, 1);
210                         }
211 #else
212                         // 64KB: 01234567
213                         fio->Fread(rom, 0x10000, 1);
214 #endif
215                 }
216                 fio->Fclose();
217                 result = true;
218         }
219         delete fio;
220         return result;
221 }
222
223 // MAIN ROM 32K
224 // or MAIN ROM 32K + MAIN RAM 32K
225
226 void SLOT_MAINROM::initialize()
227 {
228         memset(rom, 0xff, sizeof(rom));
229 #ifdef MAINROM_PLUS_RAM_32K
230         memset(ram, 0, sizeof(ram));
231 #endif
232         FILEIO* fio = new FILEIO();
233 #if defined(_MSX2P_VARIANTS)
234         if(fio->Fopen(create_local_path(_T("MSX2P.ROM")), FILEIO_READ_BINARY) ||
235 #elif defined(_MSX2_VARIANTS)
236         if(fio->Fopen(create_local_path(_T("MSX2J.ROM")), FILEIO_READ_BINARY) ||
237            fio->Fopen(create_local_path(_T("MSX2.ROM" )), FILEIO_READ_BINARY) ||
238 #else
239         if(fio->Fopen(create_local_path(_T("MSXJ.ROM")), FILEIO_READ_BINARY) ||
240            fio->Fopen(create_local_path(_T("MSX.ROM" )), FILEIO_READ_BINARY) ||
241 #endif
242            fio->Fopen(create_local_path(_T("BASIC.ROM")), FILEIO_READ_BINARY)) {
243                 fio->Fread(rom, sizeof(rom), 1);
244                 fio->Fclose();
245         }
246         delete fio;
247         
248         SET_BANK(0x0000, 0x7fff, wdmy, rom);
249 #ifdef MAINROM_PLUS_RAM_32K
250         SET_BANK(0x8000, 0xffff, ram, ram);
251 #else
252         SET_BANK(0x8000, 0xffff, wdmy, rdmy);
253 #endif
254 }
255
256 void SLOT_MAINROM::write_data8(uint32_t addr, uint32_t data)
257 {
258         wbank[addr >> 13][addr & 0x1fff] = data;
259 }
260
261 uint32_t SLOT_MAINROM::read_data8(uint32_t addr)
262 {
263         return rbank[addr >> 13][addr & 0x1fff];
264 }
265
266 #define SLOT_MAINROM_STATE_VERSION      1
267
268 bool SLOT_MAINROM::process_state(FILEIO* state_fio, bool loading)
269 {
270         if(!state_fio->StateCheckUint32(SLOT_MAINROM_STATE_VERSION)) {
271                 return false;
272         }
273         if(!state_fio->StateCheckInt32(this_device_id)) {
274                 return false;
275         }
276 #ifdef MAINROM_PLUS_RAM_32K
277         state_fio->StateArray(ram, sizeof(ram), 1);
278 #endif
279         return true;
280 }
281
282 // Cart
283
284 void SLOT_CART::initialize()
285 {
286         memset(rdmy, 0xff, sizeof(rdmy));
287         close_cart();
288 }
289
290 void SLOT_CART::write_data8(uint32_t addr, uint32_t data)
291 {
292 #ifdef USE_MEGAROM
293         if (ROM_KONAMI == type) {
294                 // Konami without SCC
295                 addr &= 0xffff;
296                 if ((0x6000 <=addr) && (addr < 0x8000)) {
297                         SET_BANK(0x6000, 0x7fff, wdmy, rom+0x2000*(data));
298                 }
299                 if ((0x8000 <=addr) && (addr < 0xa000)) {
300                         SET_BANK(0x8000, 0x9fff, wdmy, rom+0x2000*(data));
301                 }
302                 if ((0xa000 <=addr) && (addr < 0xc000)) {
303                         SET_BANK(0xa000, 0xbfff, wdmy, rom+0x2000*(data));
304                 }
305                 //wbank[addr >> 13][addr & 0x1fff] = data;
306         }
307         else if (ROM_KONAMI_SCC == type) {
308                 // Konami with SCC
309                 addr &= 0xffff;
310                 if ((0x5000 <=addr) && (addr < 0x5800)) {
311                         SET_BANK(0x4000, 0x5fff, wdmy, rom+0x2000*(data));
312                 }
313                 if ((0x7000 <=addr) && (addr < 0x7800)) {
314                         SET_BANK(0x6000, 0x7fff, wdmy, rom+0x2000*(data));
315                 }
316                 if ((0x9000 <=addr) && (addr < 0x9800)) {
317                         SET_BANK(0x8000, 0x9fff, wdmy, rom+0x2000*(data));
318                         bank_scc = ((data&0x3F)==0x3F);
319                 }
320                 if ((0xb000 <=addr) && (addr < 0xb800)) {
321                         SET_BANK(0xa000, 0xbfff, wdmy, rom+0x2000*(data));
322                 }
323                 if ((bank_scc) && (0x9000 <=addr) && (addr < 0x9900)) {
324                         d_sound->write_data8_c(SOUND_CHIP_SCC, addr & 0xFFFF, data);
325                 }
326                 //wbank[addr >> 13][addr & 0x1fff] = data;
327         }
328         else if (ROM_ASCII8 == type) {
329                 // ASCII 8Kb
330                 addr &= 0xffff;
331                 if ((0x6000 <=addr) && (addr < 0x6800)) {
332                         SET_BANK(0x4000, 0x5fff, wdmy, rom+0x2000*(data));
333                 }
334                 if ((0x6800 <=addr) && (addr < 0x7000)) {
335                         SET_BANK(0x6000, 0x7fff, wdmy, rom+0x2000*(data));
336                 }
337                 if ((0x7000 <=addr) && (addr < 0x7800)) {
338                         SET_BANK(0x8000, 0x9fff, wdmy, rom+0x2000*(data));
339                 }
340                 if ((0x7800 <=addr) && (addr < 0x8000)) {
341                         SET_BANK(0xa000, 0xbfff, wdmy, rom+0x2000*(data));
342                 }
343                 //wbank[addr >> 13][addr & 0x1fff] = data;
344         }
345         else if (ROM_ASCII16 == type) {
346                 // ASCII 16Kb
347                 data &= 0x0f;
348                 addr &= 0xffff;
349                 if ((0x6000 <=addr) && (addr < 0x6800)) {
350                         //SET_BANK(0x4000, 0x5fff, wdmy, rom+0x2000*(data*2));
351                         //SET_BANK(0x6000, 0x7fff, wdmy, rom+0x2000*(data*2+1));
352                         SET_BANK(0x4000, 0x7fff, wdmy, rom+0x2000*(data*2));
353                 }
354                 if ((0x7000 <=addr) && (addr < 0x7800)) {
355                         //SET_BANK(0x8000, 0x9fff, wdmy, rom+0x2000*(data*2));
356                         //SET_BANK(0xa000, 0xbfff, wdmy, rom+0x2000*(data*2+1));
357                         SET_BANK(0x8000, 0xbfff, wdmy, rom+0x2000*(data*2));
358                 }
359                 //wbank[addr >> 13][addr & 0x1fff] = data;
360         }
361         else /*if (ROMTYPE_NONE == type)*/ {
362                 wbank[addr >> 13][addr & 0x1fff] = data;
363         }
364 #else
365         wbank[addr >> 13][addr & 0x1fff] = data;
366 #endif
367 }
368
369 uint32_t SLOT_CART::read_data8(uint32_t addr)
370 {
371 #ifdef USE_MEGAROM
372         addr &= 0xffff;
373         if ((ROM_KONAMI_SCC == type) && (bank_scc) && (0x9000 <=addr) && (addr < 0x9900)) {
374                 return d_sound->read_data8_c(SOUND_CHIP_SCC, addr & 0xFFFF);
375         }
376         else {
377                 return rbank[addr >> 13][addr & 0x1fff];
378         }
379 #else
380         return rbank[addr >> 13][addr & 0x1fff];
381 #endif
382 }
383
384 void SLOT_CART::open_cart(const _TCHAR *file_path)
385 {
386         if(load_cart(file_path/*, rom*/)) {
387 //              SET_BANK(0x0000, 0xffff, wdmy, rom);
388                 inserted = true;
389         }
390 }
391
392 void SLOT_CART::close_cart()
393 {
394 #ifdef USE_MEGAROM
395         type = ROMTYPE_NONE;
396 //      SET_BANK(0x0000, 0xffff, wdmy, rom);
397         bank_scc = false;
398         d_sound->disable_all();
399 #endif
400         SET_BANK(0x0000, 0xffff, wdmy, rdmy);
401         inserted = false;
402 }
403
404
405 #ifdef USE_MEGAROM
406 void SLOT_CART::event_callback(int event_id, int err)
407 {
408         if(event_id == EVENT_ROMTYPE) {
409                 const _TCHAR *p;
410                 int i;
411                 for(i=0;; i++) {
412                         if ((typestr[i].type == type) || (typestr[i].type == ROMTYPE_NONE)) {
413                                 p = typestr[i].p;
414                                 break;
415                         }
416                 }
417                 emu->out_message(p);
418                 if (-1 != event_register_id) {
419                         cancel_event(this, event_register_id);
420                         event_register_id = -1;
421                 }
422         }
423 }
424 #endif
425
426 #define SLOT_CART_STATE_VERSION 1
427
428 bool SLOT_CART::process_state(FILEIO* state_fio, bool loading)
429 {
430         if(!state_fio->StateCheckUint32(SLOT_CART_STATE_VERSION)) {
431                 return false;
432         }
433         if(!state_fio->StateCheckInt32(this_device_id)) {
434                 return false;
435         }
436         state_fio->StateValue(inserted);
437 #ifdef USE_MEGAROM
438         state_fio->StateValue(type);
439         state_fio->StateValue(bank_scc);
440         /* Todo: MEGA ROM bank select */
441         /* is this OK? */
442         if(loading) {
443                 if(inserted) {
444                         SET_BANK(0x0000, 0xffff, wdmy, rom);
445                         int i32;
446                         i32 = state_fio->FgetInt32_LE() ; rbank[0] = ((i32 == -1) ? rdmy : rom + i32);
447                         i32 = state_fio->FgetInt32_LE() ; rbank[1] = ((i32 == -1) ? rdmy : rom + i32);
448                         i32 = state_fio->FgetInt32_LE() ; rbank[2] = ((i32 == -1) ? rdmy : rom + i32);
449                         i32 = state_fio->FgetInt32_LE() ; rbank[3] = ((i32 == -1) ? rdmy : rom + i32);
450                         i32 = state_fio->FgetInt32_LE() ; rbank[4] = ((i32 == -1) ? rdmy : rom + i32);
451                         i32 = state_fio->FgetInt32_LE() ; rbank[5] = ((i32 == -1) ? rdmy : rom + i32);
452                         i32 = state_fio->FgetInt32_LE() ; rbank[6] = ((i32 == -1) ? rdmy : rom + i32);
453                         i32 = state_fio->FgetInt32_LE() ; rbank[7] = ((i32 == -1) ? rdmy : rom + i32);
454                 } else {
455                         SET_BANK(0x0000, 0xffff, wdmy, rdmy);
456                 }
457         } else {
458                 if(inserted) {
459                         state_fio->FputInt32_LE(rbank[0]==rdmy ? (-1) : (int)(rbank[0] - rom));
460                         state_fio->FputInt32_LE(rbank[1]==rdmy ? (-1) : (int)(rbank[1] - rom));
461                         state_fio->FputInt32_LE(rbank[2]==rdmy ? (-1) : (int)(rbank[2] - rom));
462                         state_fio->FputInt32_LE(rbank[3]==rdmy ? (-1) : (int)(rbank[3] - rom));
463                         state_fio->FputInt32_LE(rbank[4]==rdmy ? (-1) : (int)(rbank[4] - rom));
464                         state_fio->FputInt32_LE(rbank[5]==rdmy ? (-1) : (int)(rbank[5] - rom));
465                         state_fio->FputInt32_LE(rbank[6]==rdmy ? (-1) : (int)(rbank[6] - rom));
466                         state_fio->FputInt32_LE(rbank[7]==rdmy ? (-1) : (int)(rbank[7] - rom));
467                 }
468         }
469 #else
470         // post process
471         if(loading) {
472                 if(inserted) {
473                         SET_BANK(0x0000, 0xffff, wdmy, rom);
474                 } else {
475                         SET_BANK(0x0000, 0xffff, wdmy, rdmy);
476                 }
477         }
478 #endif
479         return true;
480 }
481 // MSXDOS2
482
483 #if defined(MSXDOS2_SLOT)
484 void SLOT_MSXDOS2::initialize()
485 {
486         memset(rdmy, 0xff, sizeof(rdmy));
487         /*close_cart();*/
488         SET_BANK(0x0000, 0xffff, wdmy, rdmy);
489         mapper[0] = mapper[1] = 4;
490         FILEIO* fio = new FILEIO();
491         if(fio->Fopen(create_local_path(_T("MSXDOS2.ROM")), FILEIO_READ_BINARY)) {
492                 fio->Fread(rom, sizeof(rom), 1);
493                 fio->Fclose();
494                 mapper[0] = 0;
495                 mapper[1] = 3;
496                 SET_BANK(0x4000, 0x7fff, wdmy, rom + mapper[0] * 0x4000);
497                 SET_BANK(0x8000, 0xbfff, wdmy, rom + mapper[1] * 0x4000);
498         }
499         delete fio;
500 }
501
502 void SLOT_MSXDOS2::write_data8(uint32_t addr, uint32_t data)
503 {
504         if(addr >= 0x4000 && addr < 0xc000 && mapper[0] < 4) {
505                 addr >>= 15;
506                 addr &= 1;
507                 data &= 3;
508                 if(mapper[addr] != data) {
509                         mapper[addr] = data;
510                         SET_BANK(addr * 0x4000 + 0x4000, addr * 0x4000 + 0x7fff, wdmy, rom + data * 0x4000);
511                 }
512                 return;
513         }
514         wbank[addr >> 13][addr & 0x1fff] = data;
515 }
516
517 uint32_t SLOT_MSXDOS2::read_data8(uint32_t addr)
518 {
519         return rbank[addr >> 13][addr & 0x1fff];
520 }
521
522 #define SLOT_MSXDOS2_STATE_VERSION      1
523
524 bool SLOT_MSXDOS2::process_state(FILEIO* state_fio, bool loading)
525 {
526         if(!state_fio->StateCheckUint32(SLOT_MSXDOS2_STATE_VERSION)) {
527                 return false;
528         }
529         if(!state_fio->StateCheckInt32(this_device_id)) {
530                 return false;
531         }
532         state_fio->StateArray(mapper, sizeof(mapper), 1);
533         
534         // post process
535         if(loading) {
536                 if(mapper[0] < 4) {
537                                 SET_BANK(0x0000, 0x3fff, wdmy, rdmy);
538                                 SET_BANK(0x4000, 0x7fff, wdmy, rom + mapper[0] * 0x4000);
539                                 SET_BANK(0x8000, 0xbfff, wdmy, rom + mapper[1] * 0x4000);
540                                 SET_BANK(0xc000, 0xffff, wdmy, rdmy);
541                 } else {
542                         SET_BANK(0x0000, 0xffff, wdmy, rdmy);
543                 }
544         }
545         return true;
546 }
547
548 #endif
549
550 // LD Control
551
552 #if defined(LDC_SLOT)
553 void SLOT_LDC::initialize()
554 {
555         memset(rom, 0xff, sizeof(rom));
556         memset(rdmy, 0xff, sizeof(rdmy));
557         
558         FILEIO* fio = new FILEIO();
559         if(fio->Fopen(create_local_path(_T("PX7EXT.ROM")), FILEIO_READ_BINARY) ||
560            fio->Fopen(create_local_path(_T("EXT.ROM")   ), FILEIO_READ_BINARY)) {
561                 fio->Fread(rom, sizeof(rom), 1);
562                 fio->Fclose();
563         }
564         delete fio;
565         
566         SET_BANK(0x0000, 0x3fff, wdmy, rdmy);
567         SET_BANK(0x4000, 0x5fff, wdmy, rom);
568         SET_BANK(0x6000, 0xffff, wdmy, rdmy);
569         
570         clock = exv = ack = false;
571         
572         register_event(this, EVENT_CLOCK, 1000000.0 / 7812.5, true, NULL);
573 }
574
575 void SLOT_LDC::reset()
576 {
577         super_impose = false;
578         req_intr = false;
579         pc4 = false;
580         mute_l = mute_r = true;
581         
582         d_ldp->write_signal(SIG_LD700_MUTE_L, 1, 1);
583         d_ldp->write_signal(SIG_LD700_MUTE_R, 1, 1);
584         d_vdp->write_signal(SIG_TMS9918A_SUPER_IMPOSE, 0, 0);
585 }
586
587 void SLOT_LDC::write_data8(uint32_t addr, uint32_t data)
588 {
589         if(addr == 0x7ffe) {
590                 d_ldp->write_signal(SIG_LD700_REMOTE, data, 1);
591         } else if(addr == 0x7fff) {
592                 // super impose
593                 bool prev_super_impose = super_impose;
594                 super_impose = ((data & 1) == 0);
595                 if(super_impose) {
596                         if(req_intr && !prev_super_impose) {
597                                 d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
598                         }
599                 } else {
600                         d_cpu->write_signal(SIG_CPU_IRQ, 0, 0);
601                 }
602                 d_vdp->write_signal(SIG_TMS9918A_SUPER_IMPOSE, super_impose ? 1 : 0, 1);
603                 
604                 // mute
605                 bool prev_mute_l = mute_l;
606                 mute_l = ((data & 0x80) == 0);
607                 if(!prev_mute_l && mute_l) {
608                         mute_r = !pc4;
609                 }
610                 d_ldp->write_signal(SIG_LD700_MUTE_L, mute_l ? 1 : 0, 1);
611                 d_ldp->write_signal(SIG_LD700_MUTE_R, mute_r ? 1 : 0, 1);
612         } else {
613                 wbank[addr >> 13][addr & 0x1fff] = data;
614         }
615 }
616
617 uint32_t SLOT_LDC::read_data8(uint32_t addr)
618 {
619         if(addr == 0x7ffe) {
620                 return (clock ? 0 : 1) | (ack ? 0 : 0x80) | 0x7e;
621         } else if(addr == 0x7fff) {
622                 uint32_t data = (req_intr ? 1 : 0) | (exv ? 0 : 0x80) | 0x7e;
623                 req_intr = false;
624                 d_cpu->write_signal(SIG_CPU_IRQ, 0, 0);
625                 return data;
626         } else {
627                 return rbank[addr >> 13][addr & 0x1fff];
628         }
629 }
630
631 void SLOT_LDC::write_signal(int id, uint32_t data, uint32_t mask)
632 {
633         if(id == SIG_LDC_EXV) {
634                 bool prev = exv;
635                 exv = ((data & mask) != 0);
636                 if(prev && !exv) {
637                         req_intr = true;
638                         if(super_impose) {
639                                 d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
640                         }
641                 }
642         } else if(id == SIG_LDC_ACK) {
643                 ack = ((data & mask) != 0);
644         } else if(id == SIG_LDC_MUTE) {
645                 pc4 = ((data & mask) != 0);
646         }
647 }
648
649 void SLOT_LDC::event_callback(int event_id, int err)
650 {
651         if(event_id == EVENT_CLOCK) {
652                 clock = !clock;
653         }
654 }
655
656 #define SLOT_LDC_STATE_VERSION  1
657
658 bool SLOT_LDC::process_state(FILEIO* state_fio, bool loading)
659 {
660         if(!state_fio->StateCheckUint32(SLOT_LDC_STATE_VERSION)) {
661                 return false;
662         }
663         if(!state_fio->StateCheckInt32(this_device_id)) {
664                 return false;
665         }
666         state_fio->StateValue(clock);
667         state_fio->StateValue(exv);
668         state_fio->StateValue(ack);
669         state_fio->StateValue(super_impose);
670         state_fio->StateValue(req_intr);
671         state_fio->StateValue(pc4);
672         state_fio->StateValue(mute_l);
673         state_fio->StateValue(mute_r);
674         return true;
675 }
676 #endif
677
678 // SUBROM
679
680 #if defined(SUBROM_SLOT)
681 void SLOT_SUBROM::initialize()
682 {
683         memset(rom, 0xff, sizeof(rom));
684         memset(rdmy, 0xff, sizeof(rdmy));
685         
686         FILEIO* fio = new FILEIO();
687 #if defined(_MSX2_VARIANTS)
688         if(fio->Fopen(create_local_path(_T("MSX2JEXT.ROM")), FILEIO_READ_BINARY) ||
689            fio->Fopen(create_local_path(_T("MSX2EXT.ROM" )), FILEIO_READ_BINARY)) {
690                 fio->Fread(rom, sizeof(rom), 1);
691                 fio->Fclose();
692         }
693 #elif defined(_MSX2P_VARIANTS)
694         if(fio->Fopen(create_local_path(_T("MSX2PEXT.ROM" )), FILEIO_READ_BINARY)) {
695                 fio->Fread(rom, sizeof(rom), 1);
696                 fio->Fclose();
697         }
698         if(fio->Fopen(create_local_path(_T("KNJDRV.ROM" )), FILEIO_READ_BINARY)) {
699                 fio->Fread(rom + 0x4000, sizeof(rom) - 0x4000, 1);
700                 fio->Fclose();
701         }
702 #endif
703         delete fio;
704         
705         SET_BANK(0x4000, 0xffff, wdmy, rdmy);
706 #if defined(_MSX2_VARIANTS)
707         SET_BANK(0x0000, 0x3fff, wdmy, rom);
708 #elif defined(_MSX2P_VARIANTS)
709         SET_BANK(0x0000, 0xbfff, wdmy, rom);
710 #endif
711 }
712
713 void SLOT_SUBROM::write_data8(uint32_t addr, uint32_t data)
714 {
715         wbank[addr >> 13][addr & 0x1fff] = data;
716 }
717
718 uint32_t SLOT_SUBROM::read_data8(uint32_t addr)
719 {
720         return rbank[addr >> 13][addr & 0x1fff];
721 }
722 #endif
723
724 // FDD with ROM-PATCH
725
726 #if defined(FDD_PATCH_SLOT)
727 void SLOT_FDD_PATCH::initialize()
728 {
729         memset(rom, 0xff, sizeof(rom));
730         memset(rdmy, 0xff, sizeof(rdmy));
731         
732         FILEIO* fio = new FILEIO();
733         if(fio->Fopen(create_local_path(_T("DISK.ROM")), FILEIO_READ_BINARY)) {
734                 fio->Fread(rom, sizeof(rom), 1);
735                 fio->Fclose();
736         }
737         delete fio;
738         
739         // patch for pseudo disk bios
740         if(rom[0x0010] == 0xc3) {
741                 rom[(DSKIO  = rom[0x0011] + (int)rom[0x0012] * 256) - 0x4000] = 0xc9;
742         }
743         if(rom[0x0013] == 0xc3) {
744                 rom[(DSKCHG = rom[0x0014] + (int)rom[0x0015] * 256) - 0x4000] = 0xc9;
745         }
746         if(rom[0x0016] == 0xc3) {
747                 rom[(GETDPB = rom[0x0017] + (int)rom[0x0018] * 256) - 0x4000] = 0xc9;
748         }
749         if(rom[0x001c] == 0xc3) {
750                 rom[(DSKFMT = rom[0x001d] + (int)rom[0x001e] * 256) - 0x4000] = 0xc9;
751         }
752         if(rom[0x001f] == 0xc3) {
753                 rom[(            rom[0x0020] + (int)rom[0x0021] * 256) - 0x4000] = 0xc9;
754         }
755         SET_BANK(0x0000, 0xffff, wdmy, rdmy);
756         SET_BANK(0x4000, 0x7fff, wdmy, rom);
757 }
758
759 void SLOT_FDD_PATCH::write_data8(uint32_t addr, uint32_t data)
760 {
761         wbank[addr >> 13][addr & 0x1fff] = data;
762 }
763
764 uint32_t SLOT_FDD_PATCH::read_data8(uint32_t addr)
765 {
766         return rbank[addr >> 13][addr & 0x1fff];
767 }
768 #endif
769
770 // MAPPER RAM
771
772 #if defined(MAPPERRAM_SLOT)
773 void SLOT_MAPPERRAM::initialize()
774 {
775         memset(ram, 0xff, sizeof(ram));
776         /*close_cart();*/
777         for(int i = 0; i < 4; i++) {
778                 mapper[i] = i;
779         }
780         SET_BANK(0x0000, 0xffff, ram, ram);
781 }
782
783 void SLOT_MAPPERRAM::write_data8(uint32_t addr, uint32_t data)
784 {
785         wbank[addr >> 13][addr & 0x1fff] = data;
786 }
787
788 uint32_t SLOT_MAPPERRAM::read_data8(uint32_t addr)
789 {
790         return rbank[addr >> 13][addr & 0x1fff];
791 }
792
793 void SLOT_MAPPERRAM::write_io8(uint32_t addr, uint32_t data)
794 {
795         switch(addr & 0xff) {
796         case 0xfc:
797         case 0xfd:
798         case 0xfe:
799         case 0xff:
800                 addr &= 3;
801                 data &= MAPPERRAM_MASK;
802                 if(mapper[addr] != data) {
803                         mapper[addr] = data;
804                         SET_BANK(addr * 0x4000, addr * 0x4000 + 0x3fff, ram + data * 0x4000, ram + data * 0x4000);
805                 }
806                 break;
807         }
808 }
809
810 #define SLOT_MAPPERRAM_STATE_VERSION    1
811
812 bool SLOT_MAPPERRAM::process_state(FILEIO* state_fio, bool loading)
813 {
814         if(!state_fio->StateCheckUint32(SLOT_MAPPERRAM_STATE_VERSION)) {
815                 return false;
816         }
817         if(!state_fio->StateCheckInt32(this_device_id)) {
818                 return false;
819         }
820         state_fio->StateArray(ram, sizeof(ram), 1);
821         state_fio->StateArray(mapper, sizeof(mapper), 1);
822         
823         // post process
824         if(loading) {
825                 SET_BANK(0x0000, 0x3fff, ram + mapper[0] * 0x4000, ram + mapper[0] * 0x4000);
826                 SET_BANK(0x4000, 0x7fff, ram + mapper[1] * 0x4000, ram + mapper[1] * 0x4000);
827                 SET_BANK(0x8000, 0xbfff, ram + mapper[2] * 0x4000, ram + mapper[2] * 0x4000);
828                 SET_BANK(0xc000, 0xffff, ram + mapper[3] * 0x4000, ram + mapper[3] * 0x4000);
829         }
830         return true;
831 }
832 #endif
833
834 // NORMAL RAM 64K
835
836 #if defined(RAM64K_SLOT)
837 void SLOT_RAM64K::initialize()
838 {
839         memset(ram, 0xff, sizeof(ram));
840 }
841
842 void SLOT_RAM64K::write_data8(uint32_t addr, uint32_t data)
843 {
844         ram[addr & 0xffff] = data;
845 }
846
847 uint32_t SLOT_RAM64K::read_data8(uint32_t addr)
848 {
849         return ram[addr & 0xffff];
850 }
851
852 #define SLOT_RAM64K_STATE_VERSION       1
853
854 bool SLOT_RAM64K::process_state(FILEIO* state_fio, bool loading)
855 {
856         if(!state_fio->StateCheckUint32(SLOT_RAM64K_STATE_VERSION)) {
857                 return false;
858         }
859         if(!state_fio->StateCheckInt32(this_device_id)) {
860                 return false;
861         }
862         state_fio->StateArray(ram, sizeof(ram), 1);
863         return true;
864 }
865 #endif
866
867 // FIRMWARE 32K
868
869 #if defined(FIRMWARE32K1_SLOT)
870 void SLOT_FIRMWARE32K::initialize()
871 {
872         memset(rom, 0xff, sizeof(rom));
873         memset(rdmy, 0xff, sizeof(rdmy));
874         
875         FILEIO* fio = new FILEIO();
876         if(fio->Fopen(create_local_path(m_filename), FILEIO_READ_BINARY)) {
877                 fio->Fread(rom, sizeof(rom), 1);
878                 fio->Fclose();
879         }
880         delete fio;
881         
882         SET_BANK(0x0000, 0xffff, wdmy, rdmy);
883         SET_BANK(0x4000, 0xbfff, wdmy, rom);
884 }
885
886 void SLOT_FIRMWARE32K::write_data8(uint32_t addr, uint32_t data)
887 {
888         wbank[addr >> 13][addr & 0x1fff] = data;
889 }
890
891 uint32_t SLOT_FIRMWARE32K::read_data8(uint32_t addr)
892 {
893         return rbank[addr >> 13][addr & 0x1fff];
894 }
895 #endif
896
897 // MSX-MUSIC
898
899 #if defined(MSXMUSIC_SLOT)
900 void SLOT_MSXMUSIC::initialize()
901 {
902         memset(rom, 0xff, sizeof(rom));
903         memset(rdmy, 0xff, sizeof(rdmy));
904                 
905         SET_BANK(0x0000, 0xffff, wdmy, rom);
906         FILEIO* fio = new FILEIO();
907         if (fio->Fopen(create_local_path(_T("FMBIOS.ROM")), FILEIO_READ_BINARY)) {
908                 fio->Fread(rom, sizeof(rom), 1);
909                 fio->Fclose();
910                 SET_BANK(0x0000, 0x3fff, wdmy, rdmy);
911                 SET_BANK(0x4000, 0x7fff, wdmy, rom);
912                 SET_BANK(0x8000, 0xffff, wdmy, rdmy);
913         }
914 }
915
916 void SLOT_MSXMUSIC::write_data8(uint32_t addr, uint32_t data)
917 {
918         wbank[addr >> 13][addr & 0x1fff] = data;
919 }
920
921 uint32_t SLOT_MSXMUSIC::read_data8(uint32_t addr)
922 {
923         return rbank[addr >> 13][addr & 0x1fff];
924 }
925 #endif
926
927 // memory bus
928
929 #if defined(FDD_PATCH_SLOT)
930 void MEMORY_EX::initialize()
931 {
932         for(int i = 0; i < MAX_DRIVE; i++) {
933                 disk[i] = new DISK(emu);
934                 disk[i]->set_device_name(_T("%s/Disk #%d"), this_device_name, i + 1);
935                 disk[i]->drive_type = DRIVE_TYPE_2DD;
936         }
937 }
938
939 void MEMORY_EX::release()
940 {
941         for(int i = 0; i < MAX_DRIVE; i++) {
942                 if(disk[i]) {
943                         disk[i]->close();
944                         delete disk[i];
945                 }
946         }
947 }
948 #endif
949
950 void MEMORY_EX::reset()
951 {
952 #if defined(FDD_PATCH_SLOT)
953         for(int i = 0; i < MAX_DRIVE; i++) {
954                 access[i] = false;
955         }
956 #endif
957         ssl[0] = ssl[1] = ssl[2] = ssl[3] = 0;
958 //      update_map((0 << 0) | (1 << 2) | (2 << 4) | (3 << 6));
959         update_map(0);
960 }
961
962 void MEMORY_EX::write_data8(uint32_t addr, uint32_t data)
963 {
964         addr &= 0xffff;
965         if ((addr != 0xffff) || !expanded[(psl>>6)&3]) {
966                 d_map[addr >> 14]->write_data8(addr, data);
967         }
968         else {
969                 ssl[(psl>>6)&3] = data;
970                 update_map(psl);
971         }
972 }
973
974 uint32_t MEMORY_EX::read_data8(uint32_t addr)
975 {
976         addr &= 0xffff;
977         if ((addr != 0xffff) || !expanded[(psl>>6)&3]) {
978                 return d_map[addr >> 14]->read_data8(addr);
979         }
980         else {
981                 return 0xff ^ ssl[(psl>>6)&3];
982         }
983 }
984
985 uint32_t MEMORY_EX::fetch_op(uint32_t addr, int* wait)
986 {
987         *wait = 1;
988         return read_data8(addr);
989 }
990
991 void MEMORY_EX::write_io8(uint32_t addr, uint32_t data)
992 {
993 #if defined(MAPPERRAM_SLOT)
994 //      if(d_map[3] == d_slot[3]) {
995                 d_mapper->write_io8(addr, data);
996 //      }
997 #endif
998 }
999
1000 void MEMORY_EX::write_signal(int id, uint32_t data, uint32_t mask)
1001 {
1002         if(id == SIG_MEMORY_SEL) {
1003                 if(psl != (data & mask)) {
1004                         update_map(data & mask);
1005                 }
1006         }
1007 }
1008
1009 void MEMORY_EX::update_map(uint32_t val)
1010 {
1011         d_map[0] = d_slot[((val >> 0) & 3) | (expanded[(val >> 0) & 3] ? ((ssl[((val >> 0) & 3)] << 2) & 0x0c) : 0)];
1012         d_map[1] = d_slot[((val >> 2) & 3) | (expanded[(val >> 2) & 3] ? ((ssl[((val >> 2) & 3)] >> 0) & 0x0c) : 0)];
1013         d_map[2] = d_slot[((val >> 4) & 3) | (expanded[(val >> 4) & 3] ? ((ssl[((val >> 4) & 3)] >> 2) & 0x0c) : 0)];
1014         d_map[3] = d_slot[((val >> 6) & 3) | (expanded[(val >> 6) & 3] ? ((ssl[((val >> 6) & 3)] >> 4) & 0x0c) : 0)];
1015         psl = val;
1016 }
1017
1018 #if defined(FDD_PATCH_SLOT)
1019 static int get_track_number(int desc, int sector)
1020 {
1021         int trkside = sector / info[desc].per_track;
1022         return trkside >> (info[desc].heads - 1);
1023 }
1024
1025 static int get_side_number(int desc, int sector)
1026 {
1027         int trkside = sector / info[desc].per_track;
1028         return trkside & (info[desc].heads - 1);
1029 }
1030
1031 static bool get_track(DISK *disk, int desc, int sector)
1032 {
1033         return disk->get_track(get_track_number(desc, sector), get_side_number(desc, sector));
1034 }
1035
1036 static bool get_sector(DISK *disk, int desc, int sector)
1037 {
1038         static int last_index = 0;
1039         if(get_track(disk, desc, sector)) {
1040                 for(int i = 0; i < disk->sector_num.sd; i++) {
1041                         int j = (last_index + 2 + i) % (disk->sector_num.sd);
1042                         disk->get_sector(-1, -1, j);
1043                         if(disk->id[2] == (sector % info[desc].per_track) + 1) {
1044                                 last_index = j;
1045                                 return true;
1046                         }
1047                 }
1048         }
1049         return false;
1050 }
1051
1052 static bool get_boot_sector(DISK *disk)
1053 {
1054         if(disk->get_track(0, 0)) {
1055                 for(int i = 0; i < disk->sector_num.sd; i++) {
1056                         disk->get_sector(0, 0, i);
1057                         if(disk->id[2] == 1) {
1058                                 return true;
1059                         }
1060                 }
1061         }
1062         return false;
1063 }
1064
1065 #if defined(MSX_FDD_PATCH_WITH_2HD)
1066 static bool get_sector_2(DISK *disk, int sector)
1067 {
1068         if(get_boot_sector(disk)) {
1069                 if (512 != disk->sector_size.sd) return false;
1070                 int per_track = (int)disk->sector[0x19] * 256 + disk->sector[0x18];
1071                 if (per_track <= 0) return false;
1072                 int heads = (int)disk->sector[0x1b] * 256 + disk->sector[0x1a];
1073                 if ((heads != 2)/* && (heads != 1)*/) return false;
1074                 int trkside = sector / per_track;
1075                 int track_number = trkside >> (heads - 1);
1076                 int side_number = trkside & (heads - 1);
1077                 if(disk->get_track(track_number, side_number)) {
1078                         for(int i = 0; i < disk->sector_num.sd; i++) {
1079                                 disk->get_sector(-1, -1, i);
1080                                 if(disk->id[2] == (sector % per_track) + 1) {
1081                                         return true;
1082                                 }
1083                         }
1084                 }
1085         }
1086         return false;
1087 }
1088 #endif
1089
1090 uint32_t MEMORY_EX::read_signal(int id)
1091 {
1092         uint32_t stat = 0;
1093         for(int i = 0; i < MAX_DRIVE; i++) {
1094                 if(access[i]) {
1095                         stat |= 1 << i;
1096                         access[i] = false;
1097                 }
1098         }
1099         return stat;
1100 }
1101
1102 bool MEMORY_EX::bios_ret_z80(uint16_t PC, pair32_t* af, pair32_t* bc, pair32_t* de, pair32_t* hl, pair32_t* ix, pair32_t* iy, uint8_t* iff1)
1103 {
1104         #define AF      af->w.l
1105         #define A       af->b.h
1106         #define F       af->b.l
1107         #define BC      bc->w.l
1108         #define B       bc->b.h
1109         #define C       bc->b.l
1110         #define DE      de->w.l
1111         #define D       de->b.h
1112         #define E       de->b.l
1113         #define HL      hl->w.l
1114         #define H       hl->b.h
1115         #define L       hl->b.l
1116         
1117         #define CF      0x01
1118         
1119         if(d_map[1] == d_fdpat) {
1120                 // pseudo disk bios from fMSX
1121                 if(PC == DSKIO) {
1122 #if defined(_MSX_VDP_MESS)
1123                         d_vdp->write_signal(SIG_VDP_COMMAND_COMPLETION, 1, 1);
1124 #endif
1125                         // read/write sectors
1126                         *iff1 |= 1;
1127                         int desc = C & 7;
1128                         int drv = A;
1129                         int addr = HL;
1130                         if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
1131                                 AF = 0x0201; // not ready
1132                                 return true;
1133                         }
1134                         if(F & CF) {
1135                                 if(disk[drv]->write_protected) {
1136                                         AF = 0x0001; // write protected
1137                                         return true;
1138                                 }
1139                                 for(int sector = DE; B != 0; sector++) {
1140 #if defined(MSX_FDD_PATCH_WITH_2HD)
1141                                         if((MEDIA_TYPE_2HD == disk[drv]->media_type) || (MEDIA_TYPE_144 == disk[drv]->media_type)) {
1142                                                 if(!get_sector_2(disk[drv], sector)) {
1143                                                         AF = 0x0801; // record not found
1144                                                         return true;
1145                                                 }
1146                                         }
1147                                         else if(!get_sector(disk[drv], desc, sector)) {
1148                                                 AF = 0x0801; // record not found
1149                                                 return true;
1150                                         }
1151 #else
1152                                         if(!get_sector(disk[drv], desc, sector)) {
1153                                                 AF = 0x0801; // record not found
1154                                                 return true;
1155                                         }
1156 #endif
1157                                         access[drv] = true;
1158                                         
1159                                         if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
1160                                                 AF = 0x0801; // record not found
1161                                                 return true;
1162                                         }
1163                                         if(addr + MSX_SECTOR_SIZE/*disk[drv]->sector_size.sd*/ > 0xffff) {
1164                                                 F &= ~CF;
1165                                                 return true;
1166                                         }
1167                                         d_map[1] = d_slot[read_data8(0xf342) & 0x0f];
1168                                         for(int i = 0; i < MSX_SECTOR_SIZE/*disk[drv]->sector_size.sd*/; i++) {
1169                                                 disk[drv]->sector[i] = read_data8(addr++);
1170                                         }
1171                                         d_map[1] = d_fdpat;
1172                                         B--;
1173                                 }
1174                         } else {
1175                                 for(int sector = DE; B != 0; sector++) {
1176 #if defined(MSX_FDD_PATCH_WITH_2HD)
1177                                         if((MEDIA_TYPE_2HD == disk[drv]->media_type) || (MEDIA_TYPE_144 == disk[drv]->media_type)) {
1178                                                 if(!get_sector_2(disk[drv], sector)) {
1179                                                         AF = 0x0801; // record not found
1180                                                         return true;
1181                                                 }
1182                                         }
1183                                         else if(!get_sector(disk[drv], desc, sector)) {
1184                                                 AF = 0x0801; // record not found
1185                                                 return true;
1186                                         }
1187 #else
1188                                         if(!get_sector(disk[drv], desc, sector)) {
1189                                                 AF = 0x0801; // record not found
1190                                                 return true;
1191                                         }
1192 #endif
1193                                         access[drv] = true;
1194                                         
1195                                         if(disk[drv]->addr_crc_error && !disk[drv]->ignore_crc()) {
1196                                                 AF = 0x0801; // record not found
1197                                                 return true;
1198                                         }
1199                                         if(addr + MSX_SECTOR_SIZE/*disk[drv]->sector_size.sd*/ > 0xffff) {
1200                                                 F &= ~CF;
1201                                                 return true;
1202                                         }
1203                                         d_map[1] = d_slot[read_data8(0xf342) & 0x0f];
1204                                         for(int i = 0; i < MSX_SECTOR_SIZE/*disk[drv]->sector_size.sd*/; i++) {
1205                                                 write_data8(addr++, disk[drv]->sector[i]);
1206                                         }
1207                                         d_map[1] = d_fdpat;
1208                                         B--;
1209                                         if(disk[drv]->data_crc_error && !disk[drv]->ignore_crc()) {
1210                                                 AF = 0x0401; // data crc error
1211                                                 return true;
1212                                         }
1213                                 }
1214                         }
1215                         F &= ~CF;
1216                         return true;
1217                 } else if(PC == DSKCHG) {
1218                         // detect disk changed
1219                         *iff1 |= 1;
1220                         int drv = A;
1221                         if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
1222                                 AF = 0x0201; // not ready
1223                                 return true;
1224                         }
1225                         B = disk[drv]->changed ? 0xff : 0x01;
1226                         disk[drv]->changed = false;
1227                         F &= ~CF;
1228                         return true;
1229                 } else if(PC == GETDPB) {
1230                         // get drive parameter block
1231                         int drv = A;
1232                         if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
1233                                 AF = 0x0201; // not ready
1234                                 return true;
1235                         }
1236                         if(!get_boot_sector(disk[drv])) {
1237                                 AF = 0x0c01; // other error
1238                                 return true;
1239                         }
1240                         access[drv] = true;
1241                         
1242                         if(disk[drv]->data_crc_error && !disk[drv]->ignore_crc()) {
1243                                 AF = 0x0401; // data crc error
1244                                 return true;
1245                         }
1246                         int bytes_per_sector = (int)disk[drv]->sector[0x0c] * 256 + disk[drv]->sector[0x0b];
1247                         int sectors_per_disk = (int)disk[drv]->sector[0x14] * 256 + disk[drv]->sector[0x13];
1248                         int sectors_per_fat  = (int)disk[drv]->sector[0x17] * 256 + disk[drv]->sector[0x16];
1249                         int reserved_sectors = (int)disk[drv]->sector[0x0f] * 256 + disk[drv]->sector[0x0e];
1250                         int addr = HL + 1, num, bits;
1251                         d_map[1] = d_slot[read_data8(0xf342) & 0x0f];
1252                         write_data8(addr++, disk[drv]->sector[0x15]);   // format id [f8h-ffh]
1253                         write_data8(addr++, disk[drv]->sector[0x0b]);   // sector size
1254                         write_data8(addr++, disk[drv]->sector[0x0c]);
1255                         num = (bytes_per_sector >> 5) - 1;
1256                         for(bits = 0; num & (1 << bits); bits++);
1257                         write_data8(addr++, num);                       // directory mask/shft
1258                         write_data8(addr++, bits);
1259                         num = disk[drv]->sector[0x0d] - 1;
1260                         for(bits = 0; num & (1 << bits); bits++);
1261                         write_data8(addr++, num);                       // cluster mask/shift
1262                         write_data8(addr++, bits + 1);
1263                         write_data8(addr++, disk[drv]->sector[0x0e]);   // sector # of 1st fat
1264                         write_data8(addr++, disk[drv]->sector[0x0f]);
1265                         write_data8(addr++, disk[drv]->sector[0x10]);   // number of fats
1266                         write_data8(addr++, disk[drv]->sector[0x11]);   // number of dirent-s
1267                         num = reserved_sectors + disk[drv]->sector[0x10] * sectors_per_fat;
1268                         num += 32 * disk[drv]->sector[0x11] / bytes_per_sector;
1269                         write_data8(addr++, num & 0xff);                // sector # of data
1270                         write_data8(addr++, (num >> 8) & 0xff);
1271                         num = (sectors_per_disk - num) / disk[drv]->sector[0x0d];
1272                         write_data8(addr++, num & 0xff);                // number of clusters
1273                         write_data8(addr++, (num >> 8) & 0xff);
1274                         write_data8(addr++, disk[drv]->sector[0x16]);   // sectors per fat
1275                         num = reserved_sectors + disk[drv]->sector[0x10] * sectors_per_fat;
1276                         write_data8(addr++, num & 0xff);                // sector # of dir.
1277                         write_data8(addr, (num >> 8) & 0xff);
1278                         d_map[1] = d_fdpat;
1279                         F &= ~CF;
1280                         return true;
1281                 } else if(PC == DSKFMT) {
1282                         // format disk
1283                         *iff1 |= 1;
1284 //                      int desc = 2 - A;
1285                         int desc = A - 1; // A: 1=single-side 2=double-side
1286                         int drv = D;
1287                         if(desc != 0 && desc != 1) {
1288                                 AF = 0x0c01; // bad parameter
1289                                 return true;
1290                         }
1291                         if(!(drv < MAX_DRIVE && disk[drv]->inserted)) {
1292                                 AF = 0x0201; // not ready
1293                                 return true;
1294                         }
1295                         if(disk[drv]->write_protected) {
1296                                 AF = 0x0001; // write protected
1297                                 return true;
1298                         }
1299                         access[drv] = true;
1300                         
1301                         // physical format
1302                         int max_trkside = info[desc].sectors / info[desc].per_track;
1303                         for(int trkside = 0; trkside < max_trkside; trkside++) {
1304                                 int trk = trkside >> (info[desc].heads - 1);
1305                                 int side = trkside & (info[desc].heads - 1);
1306                                 disk[drv]->format_track(trk, side);
1307                                 for(int sct = 0; sct < info[desc].per_track; sct++) {
1308                                         disk[drv]->insert_sector(trk, side, sct + 1, 2, false, false, 0, 512);
1309                                 }
1310                         }
1311                         // fill boot block with data:
1312                         int sector = 0;
1313                         get_sector(disk[drv], desc, sector++);
1314                         memcpy(disk[drv]->sector, boot_block, 512);
1315                         uint8_t *ptr = disk[drv]->sector + 3;
1316                         memcpy(ptr, "fMSXdisk", 8); ptr += 10;          // manufacturer's id
1317                         *ptr   = info[desc].per_cluster; ptr += 4;      // sectors per cluster
1318                         *ptr++ = info[desc].names; *ptr++ = 0x00;       // number of names
1319                         *ptr++ = info[desc].sectors & 0xff;             // number of sectors
1320                         *ptr++ = (info[desc].sectors >> 8) & 0xff;
1321                         *ptr++ = desc + 0xf8;                           // format id [f8h-ffh]
1322                         *ptr++ = info[desc].per_fat; *ptr++ = 0x00;     // sectors per fat
1323                         *ptr++ = info[desc].per_track; *ptr++ = 0x00;   // sectors per track
1324                         *ptr++ = info[desc].heads; *ptr = 0x00;         // number of heads
1325                         // writing fats:
1326                         for(int j = 0; j < 2; j++) {
1327                                 get_sector(disk[drv], desc, sector++);
1328                                 memset(disk[drv]->sector, 0x00, 512);
1329                                 disk[drv]->sector[0] = desc + 0xf8;
1330                                 disk[drv]->sector[1] = disk[drv]->sector[2] = 0xff;
1331                                 for(int i = info[desc].per_fat; i > 1; i--) {
1332                                         get_sector(disk[drv], desc, sector++);
1333                                         memset(disk[drv]->sector, 0x00, 512);
1334                                 }
1335                         }
1336                         for(int i = info[desc].names / 16; i; i--) {
1337                                 get_sector(disk[drv], desc, sector++);
1338                                 memset(disk[drv]->sector, 0x00, 512);
1339                         }
1340                         for(int i = info[desc].sectors - 2 * info[desc].per_fat - info[desc].names / 16 - 1; i; i--) {
1341                                 get_sector(disk[drv], desc, sector++);
1342                                 memset(disk[drv]->sector, 0xff, 512);
1343                         }
1344                         F &= ~CF;
1345                         return true;
1346                 }
1347         }
1348         return false;
1349 }
1350
1351 void MEMORY_EX::open_disk(int drv, const _TCHAR* file_path, int bank)
1352 {
1353         if(drv < MAX_DRIVE) {
1354                 disk[drv]->open(file_path, bank);
1355         }
1356 }
1357
1358 void MEMORY_EX::close_disk(int drv)
1359 {
1360         if(drv < MAX_DRIVE && disk[drv]->inserted) {
1361                 disk[drv]->close();
1362         }
1363 }
1364
1365 bool MEMORY_EX::is_disk_inserted(int drv)
1366 {
1367         if(drv < MAX_DRIVE) {
1368                 return disk[drv]->inserted;
1369         }
1370         return false;
1371 }
1372
1373 void MEMORY_EX::is_disk_protected(int drv, bool value)
1374 {
1375         if(drv < MAX_DRIVE) {
1376                 disk[drv]->write_protected = value;
1377         }
1378 }
1379
1380 bool MEMORY_EX::is_disk_protected(int drv)
1381 {
1382         if(drv < MAX_DRIVE) {
1383                 return disk[drv]->write_protected;
1384         }
1385         return false;
1386 }
1387
1388 #endif
1389
1390 #define STATE_VERSION   1
1391
1392 bool MEMORY_EX::process_state(FILEIO* state_fio, bool loading)
1393 {
1394         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1395                 return false;
1396         }
1397         if(!state_fio->StateCheckInt32(this_device_id)) {
1398                 return false;
1399         }
1400 #if defined(FDD_PATCH_SLOT)
1401         for(int i = 0; i < MAX_DRIVE; i++) {
1402                 if(!disk[i]->process_state(state_fio, loading)) {
1403                         return false;
1404                 }
1405         }
1406 #endif
1407         state_fio->StateValue(psl);
1408         state_fio->StateValue(ssl[0]);
1409         state_fio->StateValue(ssl[1]);
1410         state_fio->StateValue(ssl[2]);
1411         state_fio->StateValue(ssl[3]);
1412         
1413         // post process
1414         if(loading) {
1415                 update_map(psl);
1416         }
1417         return true;
1418 }
1419
1420 }