OSDN Git Service

65b503108defe1d7855da991671dbb0b9d52b7ac
[csp-qt/common_source_project-fm7.git] / source / src / vm / mz700 / memory.cpp
1 /*
2         SHARP MZ-700 Emulator 'EmuZ-700'
3         SHARP MZ-800 Emulator 'EmuZ-800'
4         SHARP MZ-1500 Emulator 'EmuZ-1500'
5
6         Author : Takeda.Toshiya
7         Date   : 2008.06.05 -
8
9         [ memory ]
10 */
11
12 #include "memory.h"
13 #include "../i8253.h"
14 #include "../i8255.h"
15 #if defined(_MZ800)
16 #include "../z80pio.h"
17 #endif
18
19 #define EVENT_TEMPO             0
20 #define EVENT_BLINK             1
21 #define EVENT_HBLANK            2
22 #define EVENT_HSYNC_S           3
23 #define EVENT_HSYNC_E           4
24 #if defined(_MZ1500)
25 #define EVENT_HBLANK_PCG        5
26 #endif
27
28 #define MEM_BANK_MON_L          0x01
29 #define MEM_BANK_MON_H          0x02
30 #if defined(_MZ800)
31 #define MEM_BANK_CGROM_R        0x04
32 #define MEM_BANK_CGROM_W        0x08
33 #define MEM_BANK_CGROM          (MEM_BANK_CGROM_R | MEM_BANK_CGROM_W)
34 #define MEM_BANK_VRAM           0x10
35 #endif
36 #if defined(_MZ800) || defined(_MZ1500)
37 #define MEM_BANK_PCG            0x20
38 #endif
39
40 #if defined(_MZ800)
41 #define MZ700_MODE      (dmd & 8)
42 #endif
43
44 #define SET_BANK(s, e, w, r) { \
45         int sb = (s) >> 11, eb = (e) >> 11; \
46         for(int i = sb; i <= eb; i++) { \
47                 if((w) == wdmy) { \
48                         wbank[i] = wdmy; \
49                 } else { \
50                         wbank[i] = (w) + 0x800 * (i - sb); \
51                 } \
52                 if((r) == rdmy) { \
53                         rbank[i] = rdmy; \
54                 } else { \
55                         rbank[i] = (r) + 0x800 * (i - sb); \
56                 } \
57         } \
58 }
59
60 #if defined(_MZ800)
61 #define IPL_FILE_NAME   "MZ700IPL.ROM"
62 #define EXT_FILE_NAME   "MZ800IPL.ROM"
63 #else
64 #define IPL_FILE_NAME   "IPL.ROM"
65 #define EXT_FILE_NAME   "EXT.ROM"
66 #endif
67
68 void MEMORY::initialize()
69 {
70         // init memory
71         memset(ipl, 0xff, sizeof(ipl));
72         memset(ram, 0, sizeof(ram));
73         memset(vram, 0, sizeof(vram));
74 #if defined(_MZ700) || defined(_MZ1500)
75         memset(vram + 0x800, 0x71, 0x400);
76 #endif
77 #if defined(_MZ800) || defined(_MZ1500)
78         memset(ext, 0xff, sizeof(ext));
79 #endif
80 #if defined(_MZ1500)
81         memset(pcg, 0, sizeof(pcg));
82 #endif
83         memset(font, 0, sizeof(font));
84         memset(rdmy, 0xff, sizeof(rdmy));
85         
86         // load rom images
87         FILEIO* fio = new FILEIO();
88         if(fio->Fopen(create_local_path(_T(IPL_FILE_NAME)), FILEIO_READ_BINARY)) {
89                 fio->Fread(ipl, sizeof(ipl), 1);
90                 fio->Fclose();
91         }
92 #if defined(_MZ800) || defined(_MZ1500)
93         if(fio->Fopen(create_local_path(_T(EXT_FILE_NAME)), FILEIO_READ_BINARY)) {
94                 fio->Fread(ext, sizeof(ext), 1);
95                 fio->Fclose();
96         }
97 #endif
98         if(fio->Fopen(create_local_path(_T("FONT.ROM")), FILEIO_READ_BINARY)) {
99                 fio->Fread(font, sizeof(font), 1);
100                 fio->Fclose();
101         }
102         delete fio;
103         
104 #if defined(_MZ700)
105         // init PCG-700
106         memset(pcg, 0, sizeof(pcg));
107         memcpy(pcg + 0x000, font + 0x000, 0x400);
108         memcpy(pcg + 0x800, font + 0x800, 0x400);
109 #endif
110         
111         // init memory map
112         SET_BANK(0x0000, 0xffff, ram, ram);
113         
114         // create pc palette
115 #if defined(_MZ800)
116         update_config();
117 #else
118         for(int i = 0; i < 8; i++) {
119                 palette_pc[i] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);
120         }
121 #endif
122         
123         // register event
124         register_vline_event(this);
125         register_event_by_clock(this, EVENT_TEMPO, CPU_CLOCKS / 64, true, NULL);        // 32hz * 2
126         register_event_by_clock(this, EVENT_BLINK, CPU_CLOCKS / 3, true, NULL); // 1.5hz * 2
127 }
128
129
130 void MEMORY::reset()
131 {
132 #if defined(_MZ800)
133         // check dip-switch
134         is_mz800 = (config.boot_mode == 0);
135 #endif
136         
137         // reset memory map
138         mem_bank = MEM_BANK_MON_L | MEM_BANK_MON_H;
139 #if defined(_MZ800)
140         // TODO: check initial params
141         wf = rf = 0x01;
142         dmd = 0x00;
143         vram_addr_top = 0x9fff;
144 #elif defined(_MZ1500)
145         pcg_bank = 0;
146 #endif
147         update_map_low();
148         update_map_middle();
149         update_map_high();
150         
151         // reset crtc
152 #if defined(_MZ800)
153         sof = 0;
154         sw = 125;
155         ssa = 0;
156         sea = 125;
157 #endif
158         blink = tempo = false;
159         vblank = vsync = true;
160         hblank = hsync = true;
161 #if defined(_MZ700) || defined(_MZ1500)
162         hblank_vram = true;
163 #if defined(_MZ1500)
164         hblank_pcg = true;
165 #endif
166 #endif
167         
168 #if defined(_MZ700)
169         // reset PCG-700
170         pcg_data = pcg_addr = 0;
171         pcg_ctrl = 0xff;
172 #endif
173         
174         // reset palette
175 #if defined(_MZ800)
176         palette_sw = 0;
177         for(int i = 0; i < 4; i++) {
178                 palette[i] = i;
179         }
180         for(int i = 0; i < 16; i++) {
181                 palette16[i] = i;
182         }
183 #elif defined(_MZ1500)
184         for(int i = 0; i < 8; i++) {
185                 palette[i] = i;
186         }
187 #endif
188         
189         // motor is always rotating...
190         d_pio->write_signal(SIG_I8255_PORT_C, 0xff, 0x10);
191 }
192
193 #if defined(_MZ800)
194 void MEMORY::update_config()
195 {
196         if(config.monitor_type == 0) {
197                 // color
198                 for(int i = 0; i < 8; i++) {
199                         palette_pc[i] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);
200                 }
201                 for(int i = 0; i < 16; i++) {
202                         int val = (i & 8) ? 255 : 127;
203                         palette_mz800_pc[i] = RGB_COLOR((i & 2) ? val : 0, (i & 4) ? val : 0, (i & 1) ? val : 0);
204                 }
205         } else {
206                 // monochrome
207                 for(int i = 0; i < 8; i++) {
208                         palette_pc[i] = RGB_COLOR(255 * i / 7, 255 * i / 7, 255 * i / 7);
209                 }
210                 for(int i = 0; i < 16; i++) {
211                         palette_mz800_pc[i] = RGB_COLOR(255 * i / 15, 255 * i / 15, 255 * i / 15);
212                 }
213         }
214         palette_mz800_pc[8] = palette_mz800_pc[7];
215 }
216 #endif
217
218 void MEMORY::event_vline(int v, int clock)
219 {
220         // vblank / vsync
221         set_vblank(v >= 200);
222 #if defined(_MZ800)
223         vsync = (v >= 240 && v <= 242);
224 #else
225         vsync = (v >= 221 && v <= 223);
226 #endif
227         
228         // hblank / hsync
229         set_hblank(false);
230 #if defined(_MZ800)
231         register_event_by_clock(this, EVENT_HBLANK, 128, false, NULL);  // PAL 50Hz
232         register_event_by_clock(this, EVENT_HSYNC_S, 161, false, NULL);
233         register_event_by_clock(this, EVENT_HSYNC_E, 177, false, NULL);
234 #else
235         register_event_by_clock(this, EVENT_HBLANK, 165, false, NULL);  // NTSC 60Hz
236 //      register_event_by_clock(this, EVENT_HSYNC_S, 180, false, NULL);
237 //      register_event_by_clock(this, EVENT_HSYNC_E, 194, false, NULL);
238 #endif
239         
240 #if defined(_MZ700) || defined(_MZ1500)
241         // memory wait for vram
242         hblank_vram = false;
243 #if defined(_MZ1500)
244         // memory wait for pcg
245         register_event_by_clock(this, EVENT_HBLANK_PCG, 170, false, NULL);
246         hblank_pcg = false;
247 #endif
248 #endif
249         
250         // draw one line
251         if(v < 200) {
252 #if defined(_MZ800)
253                 switch(dmd & 0x0f) {
254                 case 0x00:      // 320x200,4col
255                 case 0x01:
256                         draw_line_320x200_2bpp(v);
257                         break;
258                 case 0x02:      // 320x200,16col
259                         draw_line_320x200_4bpp(v);
260                         break;
261                 case 0x04:      // 640x200,2col
262                 case 0x05:
263                         draw_line_640x200_1bpp(v);
264                         break;
265                 case 0x06:      // 640x200,4col
266                         draw_line_640x200_2bpp(v);
267                         break;
268                 case 0x08:      // MZ-700
269                         draw_line_mz700(v);
270                         break;
271                 }
272 #else
273                 draw_line(v);
274 #endif
275         }
276 }
277
278 void MEMORY::event_callback(int event_id, int err)
279 {
280         if(event_id == EVENT_TEMPO) {
281                 // 32KHz
282                 tempo = !tempo;
283         } else if(event_id == EVENT_BLINK) {
284                 // 556 OUT (1.5KHz) -> 8255:PC6
285                 d_pio->write_signal(SIG_I8255_PORT_C, (blink = !blink) ? 0xff : 0, 0x40);
286         } else if(event_id == EVENT_HBLANK) {
287                 set_hblank(true);
288 #if defined(_MZ700) || defined(_MZ1500)
289                 if(hblank_vram) {
290                         // wait because vram is accessed
291                         d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);
292                 }
293                 hblank_vram = true;
294 #endif
295         } else if(event_id == EVENT_HSYNC_S) {
296                 hsync = true;
297         } else if(event_id == EVENT_HSYNC_E) {
298                 hsync = false;
299 #if defined(_MZ1500)
300         } else if(event_id == EVENT_HBLANK_PCG) {
301                 if(hblank_pcg) {
302                         // wait because pcg is accessed
303                         d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);
304                 }
305                 hblank_pcg = true;
306 #endif
307         }
308 }
309
310 void MEMORY::write_data8(uint32_t addr, uint32_t data)
311 {
312         addr &= 0xffff;
313 #if defined(_MZ800)
314         // MZ-800
315         if(MZ700_MODE) {
316                 if(0xe000 <= addr && addr <= 0xe00f && (mem_bank & MEM_BANK_MON_H)) {
317                         // memory mapped i/o
318                         switch(addr & 0x0f) {
319                         case 0: case 1: case 2: case 3:
320                                 d_pio->write_io8(addr & 3, data);
321                                 break;
322                         case 4: case 5: case 6: case 7:
323                                 d_pit->write_io8(addr & 3, data);
324                                 break;
325                         case 8:
326                                 // 8253 gate0
327 //                              d_pit->write_signal(SIG_I8253_GATE_0, data, 1);
328                                 break;
329                         }
330                         return;
331                 }
332         } else {
333                 if(0x8000 <= addr && addr <= vram_addr_top && (mem_bank & MEM_BANK_VRAM)) {
334                         addr = vram_addr(addr & 0x3fff);
335                         int page;
336                         switch(wf & 0xe0) {
337                         case 0x00:      // single write
338                                 page = (dmd & 4) ? (wf & 5) : wf;
339                                 for(int i = 0, bit = 1; i < 4; i++, bit <<= 1, addr += 0x2000) {
340                                         if(page & bit) {
341                                                 vram[addr] = data;
342                                         }
343                                 }
344                                 break;
345                         case 0x20:      // exor
346                                 page = (dmd & 4) ? (wf & 5) : wf;
347                                 for(int i = 0, bit = 1; i < 4; i++, bit <<= 1, addr += 0x2000) {
348                                         if(page & bit) {
349                                                 vram[addr] ^= data;
350                                         }
351                                 }
352                                 break;
353                         case 0x40:      // or
354                                 page = (dmd & 4) ? (wf & 5) : wf;
355                                 for(int i = 0, bit = 1; i < 4; i++, bit <<= 1, addr += 0x2000) {
356                                         if(page & bit) {
357                                                 vram[addr] |= data;
358                                         }
359                                 }
360                                 break;
361                         case 0x60:      // reset
362                                 page = (dmd & 4) ? (wf & 5) : wf;
363                                 for(int i = 0, bit = 1; i < 4; i++, bit <<= 1, addr += 0x2000) {
364                                         if(page & bit) {
365                                                 vram[addr] &= ~data;
366                                         }
367                                 }
368                                 break;
369                         case 0x80:      // replace
370                         case 0xa0:
371                                 page = vram_page_mask(wf);
372                                 for(int i = 0, bit = 1; i < 4; i++, bit <<= 1, addr += 0x2000) {
373                                         if(page & bit) {
374                                                 if(wf & bit) {
375                                                         vram[addr] = data;
376                                                 } else {
377                                                         vram[addr] = 0;
378                                                 }
379                                         }
380                                 }
381                                 break;
382                         case 0xc0:      // pset
383                         case 0xe0:
384                                 page = vram_page_mask(wf);
385                                 for(int i = 0, bit = 1; i < 4; i++, bit <<= 1, addr += 0x2000) {
386                                         if(page & bit) {
387                                                 if(wf & bit) {
388                                                         vram[addr] |= data;
389                                                 } else {
390                                                         vram[addr] &= ~data;
391                                                 }
392                                         }
393                                 }
394                                 break;
395                         }
396                         return;
397                 }
398         }
399 #else
400         // MZ-700/1500
401 #if defined(_MZ1500)
402         if(mem_bank & MEM_BANK_PCG) {
403                 if(0xd000 <= addr && addr <= 0xefff) {
404                         // pcg wait
405                         if(!hblank_pcg) {
406                                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
407                                 hblank_pcg = true;
408                         }
409                 }
410         } else {
411 #endif
412                 if(mem_bank & MEM_BANK_MON_H) {
413                         if(0xd000 <= addr && addr <= 0xdfff) {
414                                 // vram wait
415                                 if(!hblank_vram) {
416                                         d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
417                                         hblank_vram = true;
418                                 }
419                         } else if(0xe000 <= addr && addr <= 0xe00f) {
420                                 // memory mapped i/o
421                                 switch(addr & 0x0f) {
422                                 case 0: case 1: case 2: case 3:
423                                         d_pio->write_io8(addr & 3, data);
424                                         break;
425                                 case 4: case 5: case 6: case 7:
426                                         d_pit->write_io8(addr & 3, data);
427                                         break;
428                                 case 8:
429                                         // 8253 gate0
430                                         d_pit->write_signal(SIG_I8253_GATE_0, data, 1);
431                                         break;
432                                 }
433                                 return;
434 #if defined(_MZ700)
435                         } else if(addr == 0xe010) {
436                                 pcg_data = data;
437                                 return;
438                         } else if(addr == 0xe011) {
439                                 pcg_addr = data;
440                                 return;
441                         } else if(addr == 0xe012) {
442                                 if(!(pcg_ctrl & 0x10) && (data & 0x10)) {
443                                         int offset = pcg_addr | ((data & 3) << 8);
444                                         offset |= (data & 4) ? 0xc00 : 0x400;
445                                         pcg[offset] = (data & 0x20) ? font[offset] : pcg_data;
446                                 }
447                                 pcg_ctrl = data;
448                                 return;
449 #endif
450                         }
451                 }
452 #if defined(_MZ1500)
453         }
454 #endif
455 #endif
456         wbank[addr >> 11][addr & 0x7ff] = data;
457 }
458
459 uint32_t MEMORY::read_data8(uint32_t addr)
460 {
461         addr &= 0xffff;
462 #if defined(_MZ800)
463         // MZ-800
464         if(MZ700_MODE) {
465                 if(0xe000 <= addr && addr <= 0xe00f && (mem_bank & MEM_BANK_MON_H)) {
466                         // memory mapped i/o
467                         switch(addr & 0x0f) {
468                         case 0: case 1: case 2: case 3:
469                                 return d_pio->read_io8(addr & 3);
470                         case 4: case 5: case 6: case 7:
471                                 return d_pit->read_io8(addr & 3);
472                         case 8:
473                                 return (hblank ? 0 : 0x80) | (tempo ? 1 : 0) | 0x7e;
474                         }
475                         return 0xff;
476                 }
477         } else {
478                 if(0x8000 <= addr && addr <= vram_addr_top && (mem_bank & MEM_BANK_VRAM)) {
479                         addr = vram_addr(addr & 0x3fff);
480                         if(rf & 0x80) {
481                                 int page = vram_page_mask(rf);
482                                 uint32_t result = 0xff;
483                                 for(int bit2 = 1; bit2 <= 0x80; bit2 <<= 1) {
484                                         uint32_t addr2 = addr;
485                                         for(int i = 0, bit = 1; i < 4; i++, bit <<= 1, addr2 += 0x2000) {
486                                                 if((page & bit) && (vram[addr2] & bit2) != ((rf & bit) ? bit2 : 0)) {
487                                                         result &= ~bit2;
488                                                         break;
489                                                 }
490                                         }
491                                 }
492                                 return result;
493                         } else {
494                                 int page = vram_page_mask(rf) & rf;
495                                 for(int i = 0, bit = 1; i < 4; i++, bit <<= 1, addr += 0x2000) {
496                                         if(page & bit) {
497                                                 return vram[addr];
498                                         }
499                                 }
500                         }
501                         return 0xff;
502                 }
503         }
504 #else
505         // MZ-700/1500
506 #if defined(_MZ1500)
507         if(mem_bank & MEM_BANK_PCG) {
508                 if(0xd000 <= addr && addr <= 0xefff) {
509                         // pcg wait
510                         if(!hblank_pcg) {
511                                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
512                                 hblank_pcg = true;
513                         }
514                 }
515         } else {
516 #endif
517                 if(mem_bank & MEM_BANK_MON_H) {
518                         if(0xd000 <= addr && addr <= 0xdfff) {
519                                 // vram wait
520                                 if(!hblank_vram) {
521                                         d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
522                                         hblank_vram = true;
523                                 }
524                         } else if(0xe000 <= addr && addr <= 0xe00f) {
525                                 // memory mapped i/o
526                                 switch(addr & 0x0f) {
527                                 case 0: case 1: case 2: case 3:
528                                         return d_pio->read_io8(addr & 3);
529                                 case 4: case 5: case 6: case 7:
530                                         return d_pit->read_io8(addr & 3);
531                                 case 8:
532                                         return (hblank ? 0 : 0x80) | (tempo ? 1 : 0) | 0x7e;
533                                 }
534                                 return 0xff;
535                         }
536                 }
537 #if defined(_MZ1500)
538         }
539 #endif
540 #endif
541         return rbank[addr >> 11][addr & 0x7ff];
542 }
543
544 void MEMORY::write_data8w(uint32_t addr, uint32_t data, int* wait)
545 {
546         *wait = ((mem_bank & MEM_BANK_MON_L) && addr < 0x1000) ? 1 : 0;
547         write_data8(addr, data);
548 }
549
550 uint32_t MEMORY::read_data8w(uint32_t addr, int* wait)
551 {
552         *wait = ((mem_bank & MEM_BANK_MON_L) && addr < 0x1000) ? 1 : 0;
553         return read_data8(addr);
554 }
555
556 void MEMORY::write_io8(uint32_t addr, uint32_t data)
557 {
558         switch(addr & 0xff) {
559 #if defined(_MZ800)
560         case 0xcc:
561                 wf = data;
562                 break;
563         case 0xcd:
564                 rf = data;
565                 break;
566         case 0xce:
567                 vram_addr_top = (data & 4) ? 0xbfff : 0x9fff;
568                 dmd = data;
569                 update_map_middle();
570                 break;
571         case 0xcf:
572                 switch(addr & 0x7ff) {
573                 case 0x1cf:
574                         sof = (sof & 0xf00) | data;
575                         break;
576                 case 0x2cf:
577                         sof = (sof & 0x0ff) | ((data & 3) << 8);
578                         break;
579                 case 0x3cf:
580                         sw = data & 0x7f;
581                         break;
582                 case 0x4cf:
583                         ssa = data & 0x7f;
584                         break;
585                 case 0x5cf:
586                         sea = data & 0x7f;
587                         break;
588                 }
589                 break;
590 #endif
591         case 0xe0:
592                 mem_bank &= ~MEM_BANK_MON_L;
593 #if defined(_MZ800)
594                 mem_bank &= ~MEM_BANK_CGROM;
595 #endif
596                 update_map_low();
597                 update_map_middle();
598                 break;
599         case 0xe1:
600                 mem_bank &= ~MEM_BANK_MON_H;
601                 update_map_high();
602                 break;
603         case 0xe2:
604                 mem_bank |= MEM_BANK_MON_L;
605                 update_map_low();
606                 break;
607         case 0xe3:
608                 mem_bank |= MEM_BANK_MON_H;
609                 update_map_high();
610                 break;
611         case 0xe4:
612                 mem_bank |= MEM_BANK_MON_L | MEM_BANK_MON_H;
613 #if defined(_MZ800)
614                 mem_bank &= ~MEM_BANK_CGROM_R;
615                 mem_bank |= MEM_BANK_CGROM_W | MEM_BANK_VRAM;
616 #elif defined(_MZ1500)
617                 mem_bank &= ~MEM_BANK_PCG;
618 #endif
619                 update_map_low();
620                 update_map_middle();
621                 update_map_high();
622                 break;
623 #if defined(_MZ800) || defined(_MZ1500)
624         case 0xe5:
625                 mem_bank |= MEM_BANK_PCG;
626 #if defined(_MZ1500)
627                 pcg_bank = data;
628 #endif
629                 update_map_high();
630                 break;
631         case 0xe6:
632                 mem_bank &= ~MEM_BANK_PCG;
633                 update_map_high();
634                 break;
635 #endif
636 #if defined(_MZ800)
637         case 0xf0:
638                 if(data & 0x40) {
639                         palette_sw = (data & 3) << 2;
640                 } else {
641                         palette[(data >> 4) & 3] = data & 0x0f;
642                 }
643                 for(int i = 0; i < 16; i++) {
644                         palette16[i] = ((i & 0x0c) == palette_sw) ? palette[i & 3] : i;
645                 }
646                 break;
647 #elif defined(_MZ1500)
648         case 0xf0:
649                 priority = data;
650                 break;
651         case 0xf1:
652                 palette[(data >> 4) & 7] = data & 7;
653                 break;
654 #endif
655         }
656 }
657
658 #if defined(_MZ800)
659 uint32_t MEMORY::read_io8(uint32_t addr)
660 {
661         switch(addr & 0xff) {
662         case 0xce:
663                 return (hblank ? 0 : 0x80) | (vblank ? 0 : 0x40) | (hsync ? 0 : 0x20) | (vsync ? 0 : 0x10) | (is_mz800 ? 2 : 0) | (tempo ? 1 : 0) | 0x0c;
664         case 0xe0:
665                 mem_bank &= ~MEM_BANK_CGROM_W;
666                 mem_bank |= MEM_BANK_CGROM_R | MEM_BANK_VRAM;
667                 update_map_middle();
668                 break;
669         case 0xe1:
670                 mem_bank &= ~(MEM_BANK_CGROM | MEM_BANK_VRAM);
671                 update_map_middle();
672                 break;
673         }
674         return 0xff;
675 }
676 #endif
677
678 void MEMORY::set_vblank(bool val)
679 {
680         if(vblank != val) {
681                 // VBLANK -> 8255:PC7
682                 d_pio->write_signal(SIG_I8255_PORT_C, val ? 0 : 0xff, 0x80);
683 #if defined(_MZ800)
684                 // VBLANK -> Z80PIO:PA5
685                 d_pio_int->write_signal(SIG_Z80PIO_PORT_A, val ? 0 : 0xff, 0x20);
686 #endif
687                 vblank = val;
688         }
689 }
690
691 void MEMORY::set_hblank(bool val)
692 {
693         if(hblank != val) {
694                 hblank = val;
695         }
696 }
697
698 void MEMORY::update_map_low()
699 {
700         if(mem_bank & MEM_BANK_MON_L) {
701                 SET_BANK(0x0000, 0x0fff, wdmy, ipl);
702         } else {
703                 SET_BANK(0x0000, 0x0fff, ram, ram);
704         }
705 }
706
707 void MEMORY::update_map_middle()
708 {
709 #if defined(_MZ800)
710         if(MZ700_MODE) {
711                 if(mem_bank & MEM_BANK_CGROM_R) {
712                         SET_BANK(0x1000, 0x1fff, wdmy, font);
713                         SET_BANK(0xc000, 0xcfff, vram + 0x2000, vram + 0x2000);
714                 } else {
715                         SET_BANK(0x1000, 0x1fff, ram + 0x1000, ram + 0x1000);
716                         SET_BANK(0xc000, 0xcfff, ram + 0xc000, ram + 0xc000);
717                 }
718         } else {
719                 if(mem_bank & MEM_BANK_CGROM) {
720                         SET_BANK(0x1000, 0x1fff, wdmy, font);
721                 } else {
722                         SET_BANK(0x1000, 0x1fff, ram + 0x1000, ram + 0x1000);
723                 }
724                 SET_BANK(0xc000, 0xcfff, ram + 0xc000, ram + 0xc000);
725         }
726 #endif
727 }
728
729 void MEMORY::update_map_high()
730 {
731 #if defined(_MZ800)
732         // MZ-800
733         if(MZ700_MODE) {
734                 if(mem_bank & MEM_BANK_PCG) {
735                         SET_BANK(0xd000, 0xffff, wdmy, rdmy);
736                 } else if(mem_bank & MEM_BANK_MON_H) {
737                         SET_BANK(0xd000, 0xdfff, vram + 0x3000, vram + 0x3000);
738                         SET_BANK(0xe000, 0xffff, wdmy, ext);
739                 } else {
740                         SET_BANK(0xd000, 0xffff, ram + 0xd000, ram + 0xd000);
741                 }
742         } else {
743                 SET_BANK(0xd000, 0xdfff, ram + 0xd000, ram + 0xd000);
744                 if(mem_bank & MEM_BANK_PCG) {
745                         SET_BANK(0xe000, 0xffff, wdmy, rdmy);
746                 } else if(mem_bank & MEM_BANK_MON_H) {
747                         SET_BANK(0xe000, 0xffff, wdmy, ext);
748                 } else {
749                         SET_BANK(0xe000, 0xffff, ram + 0xe000, ram + 0xe000);
750                 }
751         }
752 #else
753         // MZ-700/1500
754 #if defined(_MZ1500)
755         if(mem_bank & MEM_BANK_PCG) {
756                 if(pcg_bank & 3) {
757                         uint8_t *bank = pcg + ((pcg_bank & 3) - 1) * 0x2000;
758                         SET_BANK(0xd000, 0xefff, bank, bank);
759                 } else {
760                         SET_BANK(0xd000, 0xdfff, wdmy, font);   // read only
761                         SET_BANK(0xe000, 0xefff, wdmy, font);
762                 }
763                 SET_BANK(0xf000, 0xffff, wdmy, rdmy);
764         } else {
765 #endif
766                 if(mem_bank & MEM_BANK_MON_H) {
767                         SET_BANK(0xd000, 0xdfff, vram, vram);
768 #if defined(_MZ1500)
769                         SET_BANK(0xe000, 0xe7ff, wdmy, rdmy);
770                         SET_BANK(0xe800, 0xffff, wdmy, ext );
771 #else
772                         SET_BANK(0xe000, 0xffff, wdmy, rdmy);
773 #endif
774                 } else {
775                         SET_BANK(0xd000, 0xffff, ram + 0xd000, ram + 0xd000);
776                 }
777 #if defined(_MZ1500)
778         }
779 #endif
780 #endif
781 }
782
783 #if defined(_MZ800)
784 int MEMORY::vram_page_mask(uint8_t f)
785 {
786         switch(dmd & 7) {
787         case 0: // 320x200,4col
788         case 1:
789                 return (f & 0x10) ? (4 + 8) : (1 + 2);
790         case 2: // 320x200,16col
791                 return (1 + 2 + 4 + 8);
792         case 4: // 640x200,2col
793         case 5:
794                 return (f & 0x10) ? 4 : 1;
795         case 6: // 640x200,4col
796                 return (1 + 4);
797         }
798         return 0;
799 }
800
801 int MEMORY::vram_addr(int addr)
802 {
803         if(dmd & 4) {
804                 // 640x200
805                 if(ssa * 128 <= addr && addr < sea * 128) {
806                         addr += sof * 16;
807                         if(addr >= sea * 128) {
808                                 addr -= sw * 128;
809                         }
810                 }
811         } else {
812                 // 320x200
813                 if(ssa * 64 <= addr && addr < sea * 64) {
814                         addr += sof * 8;
815                         if(addr >= sea * 64) {
816                                 addr -= sw * 64;
817                         }
818                 }
819         }
820         return addr;
821 }
822 #endif
823
824 #if defined(_MZ700) || defined(_MZ1500)
825 void MEMORY::draw_line(int v)
826 {
827         int ptr = 40 * (v >> 3);
828 #if defined(_MZ700)
829         bool pcg_active = ((config.dipswitch & 1) && !(pcg_ctrl & 8));
830 #endif
831         
832         for(int x = 0; x < 320; x += 8) {
833                 uint8_t attr = vram[ptr | 0x800];
834 #if defined(_MZ1500)
835                 uint8_t pcg_attr = vram[ptr | 0xc00];
836 #endif
837                 uint16_t code = (vram[ptr] << 3) | ((attr & 0x80) << 4);
838                 uint8_t col_b = attr & 7;
839                 uint8_t col_f = (attr >> 4) & 7;
840 #if defined(_MZ700)
841                 uint8_t pat_t = pcg_active ? pcg[code | (v & 7)] : font[code | (v & 7)];
842 #else
843                 uint8_t pat_t = font[code | (v & 7)];
844 #endif
845                 uint8_t* dest = &screen[v][x];
846                 
847 #if defined(_MZ1500)
848                 if((priority & 1) && (pcg_attr & 8)) {
849                         uint16_t pcg_code = (vram[ptr | 0x400] << 3) | ((pcg_attr & 0xc0) << 5);
850                         uint8_t pcg_dot[8];
851                         uint8_t pat_b = pcg[pcg_code | (v & 7) | 0x0000];
852                         uint8_t pat_r = pcg[pcg_code | (v & 7) | 0x2000];
853                         uint8_t pat_g = pcg[pcg_code | (v & 7) | 0x4000];
854                         pcg_dot[0] = ((pat_b & 0x80) >> 7) | ((pat_r & 0x80) >> 6) | ((pat_g & 0x80) >> 5);
855                         pcg_dot[1] = ((pat_b & 0x40) >> 6) | ((pat_r & 0x40) >> 5) | ((pat_g & 0x40) >> 4);
856                         pcg_dot[2] = ((pat_b & 0x20) >> 5) | ((pat_r & 0x20) >> 4) | ((pat_g & 0x20) >> 3);
857                         pcg_dot[3] = ((pat_b & 0x10) >> 4) | ((pat_r & 0x10) >> 3) | ((pat_g & 0x10) >> 2);
858                         pcg_dot[4] = ((pat_b & 0x08) >> 3) | ((pat_r & 0x08) >> 2) | ((pat_g & 0x08) >> 1);
859                         pcg_dot[5] = ((pat_b & 0x04) >> 2) | ((pat_r & 0x04) >> 1) | ((pat_g & 0x04) >> 0);
860                         pcg_dot[6] = ((pat_b & 0x02) >> 1) | ((pat_r & 0x02) >> 0) | ((pat_g & 0x02) << 1);
861                         pcg_dot[7] = ((pat_b & 0x01) >> 0) | ((pat_r & 0x01) << 1) | ((pat_g & 0x01) << 2);
862                         
863                         if(priority & 2) {
864                                 // pcg > text
865                                 dest[0] = pcg_dot[0] ? pcg_dot[0] : (pat_t & 0x80) ? col_f : col_b;
866                                 dest[1] = pcg_dot[1] ? pcg_dot[1] : (pat_t & 0x40) ? col_f : col_b;
867                                 dest[2] = pcg_dot[2] ? pcg_dot[2] : (pat_t & 0x20) ? col_f : col_b;
868                                 dest[3] = pcg_dot[3] ? pcg_dot[3] : (pat_t & 0x10) ? col_f : col_b;
869                                 dest[4] = pcg_dot[4] ? pcg_dot[4] : (pat_t & 0x08) ? col_f : col_b;
870                                 dest[5] = pcg_dot[5] ? pcg_dot[5] : (pat_t & 0x04) ? col_f : col_b;
871                                 dest[6] = pcg_dot[6] ? pcg_dot[6] : (pat_t & 0x02) ? col_f : col_b;
872                                 dest[7] = pcg_dot[7] ? pcg_dot[7] : (pat_t & 0x01) ? col_f : col_b;
873                         } else {
874                                 // text_fore > pcg > text_back
875                                 dest[0] = (pat_t & 0x80) ? col_f : pcg_dot[0] ? pcg_dot[0] : col_b;
876                                 dest[1] = (pat_t & 0x40) ? col_f : pcg_dot[1] ? pcg_dot[1] : col_b;
877                                 dest[2] = (pat_t & 0x20) ? col_f : pcg_dot[2] ? pcg_dot[2] : col_b;
878                                 dest[3] = (pat_t & 0x10) ? col_f : pcg_dot[3] ? pcg_dot[3] : col_b;
879                                 dest[4] = (pat_t & 0x08) ? col_f : pcg_dot[4] ? pcg_dot[4] : col_b;
880                                 dest[5] = (pat_t & 0x04) ? col_f : pcg_dot[5] ? pcg_dot[5] : col_b;
881                                 dest[6] = (pat_t & 0x02) ? col_f : pcg_dot[6] ? pcg_dot[6] : col_b;
882                                 dest[7] = (pat_t & 0x01) ? col_f : pcg_dot[7] ? pcg_dot[7] : col_b;
883                         }
884                 } else {
885 #endif
886                         // text only
887                         dest[0] = (pat_t & 0x80) ? col_f : col_b;
888                         dest[1] = (pat_t & 0x40) ? col_f : col_b;
889                         dest[2] = (pat_t & 0x20) ? col_f : col_b;
890                         dest[3] = (pat_t & 0x10) ? col_f : col_b;
891                         dest[4] = (pat_t & 0x08) ? col_f : col_b;
892                         dest[5] = (pat_t & 0x04) ? col_f : col_b;
893                         dest[6] = (pat_t & 0x02) ? col_f : col_b;
894                         dest[7] = (pat_t & 0x01) ? col_f : col_b;
895 #if defined(_MZ1500)
896                 }
897 #endif
898                 ptr++;
899         }
900 }
901
902 void MEMORY::draw_screen()
903 {
904         // copy to real screen
905         emu->set_vm_screen_lines(200);
906         for(int y = 0; y < 200; y++) {
907                 scrntype_t* dest0 = emu->get_screen_buffer(2 * y);
908                 scrntype_t* dest1 = emu->get_screen_buffer(2 * y + 1);
909                 uint8_t* src = screen[y];
910                 
911                 for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
912 #if defined(_MZ1500)
913                         dest0[x2] = dest0[x2 + 1] = palette_pc[palette[src[x] & 7]];
914 #else
915                         dest0[x2] = dest0[x2 + 1] = palette_pc[src[x] & 7];
916 #endif
917                 }
918                 if(!config.scan_line) {
919                         my_memcpy(dest1, dest0, 640 * sizeof(scrntype_t));
920                 } else {
921                         memset(dest1, 0, 640 * sizeof(scrntype_t));
922                 }
923         }
924         emu->screen_skip_line(true);
925 }
926 #else
927 void MEMORY::draw_line_320x200_2bpp(int v)
928 {
929         int ofs1 = (dmd & 1) ? 0x4000 : 0;
930         int ofs2 = ofs1 | 0x2000;
931         int ptr = 40 * v;
932         
933         for(int x = 0; x < 320; x += 8) {
934                 int addr = vram_addr(ptr++);
935                 uint8_t pat1 = vram[addr | ofs1];
936                 uint8_t pat2 = vram[addr | ofs2];
937                 uint8_t* dest = &screen[v][x];
938                 
939                 dest[0] = palette[((pat1 & 0x01)     ) | ((pat2 & 0x01) << 1)];
940                 dest[1] = palette[((pat1 & 0x02) >> 1) | ((pat2 & 0x02)     )];
941                 dest[2] = palette[((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1)];
942                 dest[3] = palette[((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2)];
943                 dest[4] = palette[((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3)];
944                 dest[5] = palette[((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4)];
945                 dest[6] = palette[((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5)];
946                 dest[7] = palette[((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6)];
947         }
948 }
949
950 void MEMORY::draw_line_320x200_4bpp(int v)
951 {
952         int ptr = 40 * v;
953         
954         for(int x = 0; x < 320; x += 8) {
955                 int addr = vram_addr(ptr++);
956                 uint8_t pat1 = vram[addr         ];
957                 uint8_t pat2 = vram[addr | 0x2000];
958                 uint8_t pat3 = vram[addr | 0x4000];
959                 uint8_t pat4 = vram[addr | 0x6000];
960                 uint8_t* dest = &screen[v][x];
961                 
962                 dest[0] = palette16[((pat1 & 0x01)     ) | ((pat2 & 0x01) << 1) | ((pat3 & 0x01) << 2) | ((pat4 & 0x01) << 3)];
963                 dest[1] = palette16[((pat1 & 0x02) >> 1) | ((pat2 & 0x02)     ) | ((pat3 & 0x02) << 1) | ((pat4 & 0x02) << 2)];
964                 dest[2] = palette16[((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1) | ((pat3 & 0x04)     ) | ((pat4 & 0x04) << 1)];
965                 dest[3] = palette16[((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2) | ((pat3 & 0x08) >> 1) | ((pat4 & 0x08)     )];
966                 dest[4] = palette16[((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3) | ((pat3 & 0x10) >> 2) | ((pat4 & 0x10) >> 1)];
967                 dest[5] = palette16[((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4) | ((pat3 & 0x20) >> 3) | ((pat4 & 0x20) >> 2)];
968                 dest[6] = palette16[((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5) | ((pat3 & 0x40) >> 4) | ((pat4 & 0x40) >> 3)];
969                 dest[7] = palette16[((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6) | ((pat3 & 0x80) >> 5) | ((pat4 & 0x80) >> 4)];
970         }
971 }
972
973 void MEMORY::draw_line_640x200_1bpp(int v)
974 {
975         int ofs = (dmd & 1) ? 0x4000 : 0;
976         int ptr = 80 * v;
977         
978         for(int x = 0; x < 640; x += 8) {
979                 int addr = vram_addr(ptr++);
980                 uint8_t pat = vram[addr | ofs];
981                 uint8_t* dest = &screen[v][x];
982                 
983                 dest[0] = palette[(pat & 0x01)     ];
984                 dest[1] = palette[(pat & 0x02) >> 1];
985                 dest[2] = palette[(pat & 0x04) >> 2];
986                 dest[3] = palette[(pat & 0x08) >> 3];
987                 dest[4] = palette[(pat & 0x10) >> 4];
988                 dest[5] = palette[(pat & 0x20) >> 5];
989                 dest[6] = palette[(pat & 0x40) >> 6];
990                 dest[7] = palette[(pat & 0x80) >> 7];
991         }
992 }
993
994 void MEMORY::draw_line_640x200_2bpp(int v)
995 {
996         int ptr = 80 * v;
997         
998         for(int x = 0; x < 640; x += 8) {
999                 int addr = vram_addr(ptr++);
1000                 uint8_t pat1 = vram[addr         ];
1001                 uint8_t pat2 = vram[addr | 0x4000];
1002                 uint8_t* dest = &screen[v][x];
1003                 
1004                 dest[0] = palette[((pat1 & 0x01)     ) | ((pat2 & 0x01) << 1)];
1005                 dest[1] = palette[((pat1 & 0x02) >> 1) | ((pat2 & 0x02)     )];
1006                 dest[2] = palette[((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1)];
1007                 dest[3] = palette[((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2)];
1008                 dest[4] = palette[((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3)];
1009                 dest[5] = palette[((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4)];
1010                 dest[6] = palette[((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5)];
1011                 dest[7] = palette[((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6)];
1012         }
1013 }
1014
1015 void MEMORY::draw_line_mz700(int v)
1016 {
1017         int ptr = (40 * (v >> 3)) | 0x3000;
1018         
1019         for(int x = 0; x < 320; x += 8) {
1020                 uint8_t attr = vram[ptr | 0x800];
1021                 uint16_t code = (vram[ptr] << 3) | ((attr & 0x80) << 4);
1022                 uint8_t col_b = attr & 7;
1023                 uint8_t col_f = (attr >> 4) & 7;
1024                 uint8_t pat_t = vram[code | (v & 7) | 0x2000];
1025                 uint8_t* dest = &screen[v][x];
1026                 
1027                 // text only
1028                 dest[0] = (pat_t & 0x01) ? col_f : col_b;
1029                 dest[1] = (pat_t & 0x02) ? col_f : col_b;
1030                 dest[2] = (pat_t & 0x04) ? col_f : col_b;
1031                 dest[3] = (pat_t & 0x08) ? col_f : col_b;
1032                 dest[4] = (pat_t & 0x10) ? col_f : col_b;
1033                 dest[5] = (pat_t & 0x20) ? col_f : col_b;
1034                 dest[6] = (pat_t & 0x40) ? col_f : col_b;
1035                 dest[7] = (pat_t & 0x80) ? col_f : col_b;
1036                 ptr++;
1037         }
1038 }
1039
1040 void MEMORY::draw_screen()
1041 {
1042         // copy to real screen
1043         emu->set_vm_screen_lines(200);
1044         for(int y = 0; y < 200; y++) {
1045                 scrntype_t* dest0 = emu->get_screen_buffer(2 * y);
1046                 scrntype_t* dest1 = emu->get_screen_buffer(2 * y + 1);
1047                 uint8_t* src = screen[y];
1048                 
1049                 if(dmd & 8) {
1050                         // MZ-700 mode
1051                         for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
1052                                 dest0[x2] = dest0[x2 + 1] = palette_pc[src[x] & 7];
1053                         }
1054                 } else if(dmd & 4) {
1055                         // 640x200
1056                         for(int x = 0; x < 640; x++) {
1057                                 dest0[x] = palette_mz800_pc[src[x] & 15];
1058                         }
1059                 } else {
1060                         // 320x200
1061                         for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
1062                                 dest0[x2] = dest0[x2 + 1] = palette_mz800_pc[src[x] & 15];
1063                         }
1064                 }
1065                 if(!config.scan_line) {
1066                         my_memcpy(dest1, dest0, 640 * sizeof(scrntype_t));
1067                 } else {
1068                         memset(dest1, 0, 640 * sizeof(scrntype_t));
1069                 }
1070         }
1071         emu->screen_skip_line(true);
1072 }
1073 #endif
1074
1075 #define STATE_VERSION   2
1076
1077 #include "../../statesub.h"
1078
1079 void MEMORY::decl_state()
1080 {
1081         enter_decl_state(STATE_VERSION);
1082         
1083 #if defined(_MZ700)
1084         DECL_STATE_ENTRY_1D_ARRAY(&(pcg[0x400]), 0x400);
1085         DECL_STATE_ENTRY_1D_ARRAY(&(pcg[0xc00]), 0x400);
1086 #elif defined(_MZ1500)
1087         DECL_STATE_ENTRY_1D_ARRAY(pcg, sizeof(pcg));
1088 #endif
1089         DECL_STATE_ENTRY_1D_ARRAY(ram, sizeof(ram));
1090         DECL_STATE_ENTRY_1D_ARRAY(vram, sizeof(vram));
1091         DECL_STATE_ENTRY_UINT8(mem_bank);
1092 #if defined(_MZ700)
1093         DECL_STATE_ENTRY_UINT8(pcg_data);
1094         DECL_STATE_ENTRY_UINT8(pcg_addr);
1095         DECL_STATE_ENTRY_UINT8(pcg_ctrl);
1096 #elif defined(_MZ800)
1097         DECL_STATE_ENTRY_UINT8(wf);
1098         DECL_STATE_ENTRY_UINT8(rf);
1099         DECL_STATE_ENTRY_UINT8(dmd);
1100         DECL_STATE_ENTRY_UINT32(vram_addr_top);
1101         DECL_STATE_ENTRY_BOOL(is_mz800);
1102 #elif defined(_MZ1500)
1103         DECL_STATE_ENTRY_UINT8(pcg_bank);
1104 #endif
1105 #if defined(_MZ800)
1106         DECL_STATE_ENTRY_UINT16(sof);
1107         DECL_STATE_ENTRY_UINT8(sw);
1108         DECL_STATE_ENTRY_UINT8(ssa);
1109         DECL_STATE_ENTRY_UINT8(sea);
1110         DECL_STATE_ENTRY_UINT8(palette_sw);
1111         DECL_STATE_ENTRY_1D_ARRAY(palette, sizeof(palette));
1112         DECL_STATE_ENTRY_1D_ARRAY(palette16, sizeof(palette16));
1113 #elif defined(_MZ1500)
1114         DECL_STATE_ENTRY_UINT8(priority);
1115         DECL_STATE_ENTRY_1D_ARRAY(palette, sizeof(palette));
1116 #endif
1117         DECL_STATE_ENTRY_BOOL(blink);
1118         DECL_STATE_ENTRY_BOOL(tempo);
1119         DECL_STATE_ENTRY_BOOL(hblank);
1120         DECL_STATE_ENTRY_BOOL(hsync);
1121         DECL_STATE_ENTRY_BOOL(vblank);
1122         DECL_STATE_ENTRY_BOOL(vsync);
1123 #if defined(_MZ700) || defined(_MZ1500)
1124         DECL_STATE_ENTRY_BOOL(hblank_vram);
1125 #endif
1126 #if defined(_MZ1500)
1127         DECL_STATE_ENTRY_BOOL(hblank_pcg);
1128 #endif
1129 #if defined(_MZ800)
1130         DECL_STATE_ENTRY_SCRNTYPE_T_1D_ARRAY(palette_mz800_pc, sizeof(palette_mz800_pc) / sizeof(scrntype_t));
1131 #endif
1132         DECL_STATE_ENTRY_SCRNTYPE_T_1D_ARRAY(palette_pc, sizeof(palette_pc) / sizeof(scrntype_t));
1133
1134         leave_decl_state();
1135 }
1136
1137 void MEMORY::save_state(FILEIO* state_fio)
1138 {
1139         if(state_entry != NULL) {
1140                 state_entry->save_state(state_fio);
1141         }
1142 //      state_fio->FputUint32(STATE_VERSION);
1143 //      state_fio->FputInt32(this_device_id);
1144         
1145 //#if defined(_MZ700)
1146 //      state_fio->Fwrite(pcg + 0x400, 0x400, 1);
1147 //      state_fio->Fwrite(pcg + 0xc00, 0x400, 1);
1148 //#elif defined(_MZ1500)
1149 //      state_fio->Fwrite(pcg, sizeof(pcg), 1);
1150 //#endif
1151 //      state_fio->Fwrite(ram, sizeof(ram), 1);
1152 //      state_fio->Fwrite(vram, sizeof(vram), 1);
1153 //      state_fio->FputUint8(mem_bank);
1154 //#if defined(_MZ700)
1155 //      state_fio->FputUint8(pcg_data);
1156 //      state_fio->FputUint8(pcg_addr);
1157 //      state_fio->FputUint8(pcg_ctrl);
1158 //#elif defined(_MZ800)
1159 //      state_fio->FputUint8(wf);
1160 //      state_fio->FputUint8(rf);
1161 //      state_fio->FputUint8(dmd);
1162 //      state_fio->FputUint32(vram_addr_top);
1163 //      state_fio->FputBool(is_mz800);
1164 //#elif defined(_MZ1500)
1165 //      state_fio->FputUint8(pcg_bank);
1166 //#endif
1167 //#if defined(_MZ800)
1168 //      state_fio->FputUint16(sof);
1169 //      state_fio->FputUint8(sw);
1170 //      state_fio->FputUint8(ssa);
1171 //      state_fio->FputUint8(sea);
1172 //      state_fio->FputUint8(palette_sw);
1173 //      state_fio->Fwrite(palette, sizeof(palette), 1);
1174 //      state_fio->Fwrite(palette16, sizeof(palette16), 1);
1175 //#elif defined(_MZ1500)
1176 //      state_fio->FputUint8(priority);
1177 //      state_fio->Fwrite(palette, sizeof(palette), 1);
1178 //#endif
1179 //      state_fio->FputBool(blink);
1180 //      state_fio->FputBool(tempo);
1181 //      state_fio->FputBool(hblank);
1182 //      state_fio->FputBool(hsync);
1183 //      state_fio->FputBool(vblank);
1184 //      state_fio->FputBool(vsync);
1185 //#if defined(_MZ700) || defined(_MZ1500)
1186 //      state_fio->FputBool(hblank_vram);
1187 //#endif
1188 //#if defined(_MZ1500)
1189 //      state_fio->FputBool(hblank_pcg);
1190 //#endif
1191 //#if defined(_MZ800)
1192 //      state_fio->Fwrite(palette_mz800_pc, sizeof(palette_mz800_pc), 1);
1193 //#endif
1194 //      state_fio->Fwrite(palette_pc, sizeof(palette_pc), 1);
1195 }
1196
1197 bool MEMORY::load_state(FILEIO* state_fio)
1198 {
1199         bool mb = false;
1200         if(state_entry != NULL) {
1201                 mb = state_entry->load_state(state_fio);
1202         }
1203         if(!mb) {
1204                 return false;
1205         }
1206 //      if(state_fio->FgetUint32() != STATE_VERSION) {
1207 //              return false;
1208 //      }
1209 //      if(state_fio->FgetInt32() != this_device_id) {
1210 //              return false;
1211 //      }
1212 //#if defined(_MZ700)
1213 //      state_fio->Fread(pcg + 0x400, 0x400, 1);
1214 //      state_fio->Fread(pcg + 0xc00, 0x400, 1);
1215 //#elif defined(_MZ1500)
1216 //      state_fio->Fread(pcg, sizeof(pcg), 1);
1217 //#endif
1218 //      state_fio->Fread(ram, sizeof(ram), 1);
1219 //      state_fio->Fread(vram, sizeof(vram), 1);
1220 //      mem_bank = state_fio->FgetUint8();
1221 //#if defined(_MZ700)
1222 //      pcg_data = state_fio->FgetUint8();
1223 //      pcg_addr = state_fio->FgetUint8();
1224 //      pcg_ctrl = state_fio->FgetUint8();
1225 //#elif defined(_MZ800)
1226 //      wf = state_fio->FgetUint8();
1227 //      rf = state_fio->FgetUint8();
1228 //      dmd = state_fio->FgetUint8();
1229 //      vram_addr_top = state_fio->FgetUint32();
1230 //      is_mz800 = state_fio->FgetBool();
1231 //#elif defined(_MZ1500)
1232 //      pcg_bank = state_fio->FgetUint8();
1233 //#endif
1234 //#if defined(_MZ800)
1235 //      sof = state_fio->FgetUint16();
1236 //      sw = state_fio->FgetUint8();
1237 //      ssa = state_fio->FgetUint8();
1238 //      sea = state_fio->FgetUint8();
1239 //      palette_sw = state_fio->FgetUint8();
1240 //      state_fio->Fread(palette, sizeof(palette), 1);
1241 //      state_fio->Fread(palette16, sizeof(palette16), 1);
1242 //#elif defined(_MZ1500)
1243 //      priority = state_fio->FgetUint8();
1244 //      state_fio->Fread(palette, sizeof(palette), 1);
1245 //#endif
1246 //      blink = state_fio->FgetBool();
1247 //      tempo = state_fio->FgetBool();
1248 //      hblank = state_fio->FgetBool();
1249 //      hsync = state_fio->FgetBool();
1250 //      vblank = state_fio->FgetBool();
1251 //      vsync = state_fio->FgetBool();
1252 //#if defined(_MZ700) || defined(_MZ1500)
1253 //      hblank_vram = state_fio->FgetBool();
1254 //#endif
1255 //#if defined(_MZ1500)
1256 //      hblank_pcg = state_fio->FgetBool();
1257 //#endif
1258 //#if defined(_MZ800)
1259 //      state_fio->Fread(palette_mz800_pc, sizeof(palette_mz800_pc), 1);
1260 //#endif
1261 //      state_fio->Fread(palette_pc, sizeof(palette_pc), 1);
1262         
1263         // post process
1264         update_map_low();
1265         update_map_middle();
1266         update_map_high();
1267         return true;
1268 }
1269
1270 bool MEMORY::process_state(FILEIO* state_fio, bool loading)
1271 {
1272         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1273                 return false;
1274         }
1275         if(!state_fio->StateCheckInt32(this_device_id)) {
1276                 return false;
1277         }
1278 #if defined(_MZ700)
1279         state_fio->StateBuffer(pcg + 0x400, 0x400, 1);
1280         state_fio->StateBuffer(pcg + 0xc00, 0x400, 1);
1281 #elif defined(_MZ1500)
1282         state_fio->StateBuffer(pcg, sizeof(pcg), 1);
1283 #endif
1284         state_fio->StateBuffer(ram, sizeof(ram), 1);
1285         state_fio->StateBuffer(vram, sizeof(vram), 1);
1286         state_fio->StateUint8(mem_bank);
1287 #if defined(_MZ700)
1288         state_fio->StateUint8(pcg_data);
1289         state_fio->StateUint8(pcg_addr);
1290         state_fio->StateUint8(pcg_ctrl);
1291 #elif defined(_MZ800)
1292         state_fio->StateUint8(wf);
1293         state_fio->StateUint8(rf);
1294         state_fio->StateUint8(dmd);
1295         state_fio->StateUint32(vram_addr_top);
1296         state_fio->StateBool(is_mz800);
1297 #elif defined(_MZ1500)
1298         state_fio->StateUint8(pcg_bank);
1299 #endif
1300 #if defined(_MZ800)
1301         state_fio->StateUint16(sof);
1302         state_fio->StateUint8(sw);
1303         state_fio->StateUint8(ssa);
1304         state_fio->StateUint8(sea);
1305         state_fio->StateUint8(palette_sw);
1306         state_fio->StateBuffer(palette, sizeof(palette), 1);
1307         state_fio->StateBuffer(palette16, sizeof(palette16), 1);
1308 #elif defined(_MZ1500)
1309         state_fio->StateUint8(priority);
1310         state_fio->StateBuffer(palette, sizeof(palette), 1);
1311 #endif
1312         state_fio->StateBool(blink);
1313         state_fio->StateBool(tempo);
1314         state_fio->StateBool(hblank);
1315         state_fio->StateBool(hsync);
1316         state_fio->StateBool(vblank);
1317         state_fio->StateBool(vsync);
1318 #if defined(_MZ700) || defined(_MZ1500)
1319         state_fio->StateBool(hblank_vram);
1320 #endif
1321 #if defined(_MZ1500)
1322         state_fio->StateBool(hblank_pcg);
1323 #endif
1324 #if defined(_MZ800)
1325         state_fio->StateBuffer(palette_mz800_pc, sizeof(palette_mz800_pc), 1);
1326 #endif
1327         state_fio->StateBuffer(palette_pc, sizeof(palette_pc), 1);
1328         
1329         // post process
1330         if(loading) {
1331                 update_map_low();
1332                 update_map_middle();
1333                 update_map_high();
1334         }
1335         return true;
1336 }