OSDN Git Service

[VM][Towns] Initial start.Still not working.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmtowns / memory.cpp
1 /*
2         FUJITSU FMR-50 Emulator 'eFMR-50'
3         FUJITSU FMR-60 Emulator 'eFMR-60'
4
5         Author : Takeda.Toshiya
6         Date   : 2008.04.29 -
7
8         [ memory and crtc ]
9 */
10
11 #include "memory.h"
12 #if defined(HAS_I286)
13 #include "../i286.h"
14 #else
15 #include "../i386.h"
16 #endif
17
18 static const uint8_t bios1[] = {
19         0xFA,                           // cli
20         0xDB,0xE3,                      // fninit
21         0xB8,0xA0,0xF7,                 // mov  ax,F7A0
22         0x8E,0xD0,                      // mov  ss,ax
23         0xBC,0x7E,0x05,                 // mov  sp,057E
24         // init i/o
25         0xB4,0x80,                      // mov  ah,80
26         0x9A,0x14,0x00,0xFB,0xFF,       // call far FFFB:0014
27         // boot from fdd
28         0xB4,0x81,                      // mov  ah,81
29         0x9A,0x14,0x00,0xFB,0xFF,       // call far FFFB:0014
30         0x73,0x0B,                      // jnb  $+11
31         0x74,0xF5,                      // jz   $-11
32         // boot from scsi-hdd
33         0xB4,0x82,                      // mov  ah,82
34         0x9A,0x14,0x00,0xFB,0xFF,       // call far FFFB:0014
35         0x72,0xEC,                      // jb   $-20
36         // goto ipl
37         0x9A,0x04,0x00,0x00,0xB0,       // call far B000:0004
38         0xEB,0xE7                       // jmp $-25
39 };
40
41 static const uint8_t bios2[] = {
42         0xEA,0x00,0x00,0x00,0xFC,       // jmp  FC00:0000
43         0x00,0x00,0x00,
44         0xcf                            // iret
45 };
46
47 #define SET_BANK(s, e, w, r) { \
48         int sb = (s) >> 11, eb = (e) >> 11; \
49         for(int i = sb; i <= eb; i++) { \
50                 if((w) == wdmy) { \
51                         wbank[i] = wdmy; \
52                 } else { \
53                         wbank[i] = (w) + 0x800 * (i - sb); \
54                 } \
55                 if((r) == rdmy) { \
56                         rbank[i] = rdmy; \
57                 } else { \
58                         rbank[i] = (r) + 0x800 * (i - sb); \
59                 } \
60         } \
61 }
62
63 void MEMORY::initialize()
64 {
65         // init memory
66         memset(ram, 0, sizeof(ram));
67         memset(vram, 0, sizeof(vram));
68         memset(cvram, 0, sizeof(cvram));
69 #ifdef _FMR60
70         memset(avram, 0, sizeof(avram));
71 #else
72         memset(kvram, 0, sizeof(kvram));
73         memset(dummy, 0, sizeof(dummy));
74 #endif
75         memset(ipl, 0xff, sizeof(ipl));
76 #ifdef _FMR60
77         memset(ank24, 0xff, sizeof(ank24));
78         memset(kanji24, 0xff, sizeof(kanji24));
79 #else
80         memset(ank8, 0xff, sizeof(ank8));
81         memset(ank16, 0xff, sizeof(ank16));
82         memset(kanji16, 0xff, sizeof(kanji16));
83 #endif
84         memset(rdmy, 0xff, sizeof(rdmy));
85         
86         // load rom image
87         FILEIO* fio = new FILEIO();
88         if(fio->Fopen(create_local_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
89                 fio->Fread(ipl, sizeof(ipl), 1);
90                 fio->Fclose();
91         } else {
92                 // load pseudo ipl
93                 memcpy(ipl + 0x0000, bios1, sizeof(bios1));
94                 memcpy(ipl + 0x3ff0, bios2, sizeof(bios2));
95         }
96 #ifdef _FMR60
97         if(fio->Fopen(create_local_path(_T("ANK24.ROM")), FILEIO_READ_BINARY)) {
98                 fio->Fread(ank24, sizeof(ank24), 1);
99                 fio->Fclose();
100         }
101         if(fio->Fopen(create_local_path(_T("KANJI24.ROM")), FILEIO_READ_BINARY)) {
102                 fio->Fread(kanji24, sizeof(kanji24), 1);
103                 fio->Fclose();
104         }
105 #else
106         if(fio->Fopen(create_local_path(_T("ANK8.ROM")), FILEIO_READ_BINARY)) {
107                 fio->Fread(ank8, sizeof(ank8), 1);
108                 fio->Fclose();
109         }
110         if(fio->Fopen(create_local_path(_T("ANK16.ROM")), FILEIO_READ_BINARY)) {
111                 fio->Fread(ank16, sizeof(ank16), 1);
112                 fio->Fclose();
113         }
114         if(fio->Fopen(create_local_path(_T("KANJI16.ROM")), FILEIO_READ_BINARY)) {
115                 fio->Fread(kanji16, sizeof(kanji16), 1);
116                 fio->Fclose();
117         }
118 #endif
119         delete fio;
120         
121         // set memory
122         SET_BANK(0x000000, 0xffffff, wdmy, rdmy);
123         SET_BANK(0x000000, sizeof(ram) - 1, ram, ram);
124 #ifdef _FMR60
125         SET_BANK(0xff8000, 0xff9fff, cvram, cvram);
126         SET_BANK(0xffa000, 0xffbfff, avram, avram);
127 #endif
128         SET_BANK(0xffc000, 0xffffff, wdmy, ipl);
129         
130         // set palette
131         for(int i = 0; i < 8; i++) {
132                 dpal[i] = i;
133                 apal[i][0] = (i & 1) ? 0xf0 : 0;
134                 apal[i][1] = (i & 2) ? 0xf0 : 0;
135                 apal[i][2] = (i & 4) ? 0xf0 : 0;
136         }
137         for(int i = 0; i < 16; i++) {
138                 if(i & 8) {
139                         palette_cg[i] = RGB_COLOR(i & 2 ? 255 : 0, i & 4 ? 255 : 0, i & 1 ? 255 : 0);
140                 } else {
141                         palette_cg[i] = RGB_COLOR(i & 2 ? 127 : 0, i & 4 ? 127 : 0, i & 1 ? 127 : 0);
142                 }
143                 palette_txt[i] = palette_cg[i];
144         }
145         palette_txt[0] = RGB_COLOR(63, 63, 63);
146         apalsel = 0;
147         
148         // register event
149         register_frame_event(this);
150 }
151
152 void MEMORY::reset()
153 {
154         // reset memory
155         protect = rst = 0;
156         mainmem = rplane = wplane = 0;
157 #ifndef _FMR60
158         pagesel = ankcg = 0;
159 #endif
160         update_bank();
161         
162         // reset crtc
163         blink = 0;
164         apalsel = 0;
165         outctrl = 0xf;
166 #ifndef _FMR60
167         dispctrl = 0x47;
168         mix = 8;
169         accaddr = dispaddr = 0;
170         kj_l = kj_h = kj_ofs = kj_row = 0;
171         
172         // reset logical operation
173         cmdreg = maskreg = compbit = bankdis = 0;
174         memset(compreg, sizeof(compreg), 0xff);
175 #endif
176         dma_addr_reg = dma_wrap_reg = 0;
177         dma_addr_mask = 0x00ffffff;
178         d_cpu->set_address_mask(0x00ffffff);
179 }
180
181 void MEMORY::write_data8(uint32_t addr, uint32_t data)
182 {
183         if(addr & 0xff000000) {
184                 // > 16MB
185                 return;
186         }
187         if(!mainmem) {
188 #ifdef _FMR60
189                 if(0xc0000 <= addr && addr < 0xe0000) {
190                         addr &= 0x1ffff;
191                         for(int pl = 0; pl < 4; pl++) {
192                                 if(wplane & (1 << pl)) {
193                                         vram[addr + 0x20000 * pl] = data;
194                                 }
195                         }
196                 }
197 #else
198                 if(0xc0000 <= addr && addr < 0xc8000) {
199                         // vram
200                         uint32_t page;
201                         if(dispctrl & 0x40) {
202                                 // 400 line
203                                 addr = ((pagesel & 0x10) << 13) | (addr & 0x7fff);
204                                 page = 0x8000;
205                         } else {
206                                 // 200 line
207                                 addr = ((pagesel & 0x18) << 13) | (addr & 0x3fff);
208                                 page = 0x4000;
209                         }
210                         if(cmdreg & 0x80) {
211                                 // logical operations
212                                 if((cmdreg & 7) == 7) {
213                                         // compare
214                                         compbit = 0;
215                                         for(uint8_t bit = 1; bit <= 0x80; bit <<= 1) {
216                                                 uint8_t val = 0;
217                                                 for(int pl = 0; pl < 4; pl++) {
218                                                         if(vram[addr + page * pl] & bit) {
219                                                                 val |= 1 << pl;
220                                                         }
221                                                 }
222                                                 for(int i = 0; i < 8; i++) {
223                                                         if((compreg[i] & 0x80) && (compreg[i] & 0xf) == val) {
224                                                                 compbit |= bit;
225                                                         }
226                                                 }
227                                         }
228                                 } else {
229                                         uint8_t mask = maskreg | ~data, val[4];
230                                         for(int pl = 0; pl < 4; pl++) {
231                                                 val[pl] = (imgcol & (1 << pl)) ? 0xff : 0;
232                                         }
233                                         switch(cmdreg & 7) {
234                                         case 2: // or
235                                                 for(int pl = 0; pl < 4; pl++) {
236                                                         val[pl] |= vram[addr + page * pl];
237                                                 }
238                                                 break;
239                                         case 3: // and
240                                                 for(int pl = 0; pl < 4; pl++) {
241                                                         val[pl] &= vram[addr + page * pl];
242                                                 }
243                                                 break;
244                                         case 4: // xor
245                                                 for(int pl = 0; pl < 4; pl++) {
246                                                         val[pl] ^= vram[addr + page * pl];
247                                                 }
248                                                 break;
249                                         case 5: // not
250                                                 for(int pl = 0; pl < 4; pl++) {
251                                                         val[pl] = ~vram[addr + page * pl];
252                                                 }
253                                                 break;
254                                         case 6: // tile
255                                                 for(int pl = 0; pl < 4; pl++) {
256                                                         val[pl] = tilereg[pl];
257                                                 }
258                                                 break;
259                                         }
260                                         for(int pl = 0; pl < 4; pl++) {
261                                                 if(!(bankdis & (1 << pl))) {
262                                                         vram[addr + page * pl] &= mask;
263                                                         vram[addr + page * pl] |= val[pl] & ~mask;
264                                                 }
265                                         }
266                                 }
267                         } else {
268                                 for(int pl = 0; pl < 4; pl++) {
269                                         if(wplane & (1 << pl)) {
270                                                 vram[addr + page * pl] = data;
271                                         }
272                                 }
273                         }
274                         return;
275                 } else if(0xcff80 <= addr && addr < 0xcffe0) {
276 #ifdef _DEBUG_LOG
277 //                      this->out_debug_log(_T("MW\t%4x, %2x\n"), addr, data);
278 #endif
279                         // memory mapped i/o
280                         switch(addr & 0xffff) {
281                         case 0xff80:
282                                 // mix register
283                                 mix = data;
284                                 break;
285                         case 0xff81:
286                                 // update register
287                                 wplane = data & 7;
288                                 rplane = (data >> 6) & 3;
289                                 update_bank();
290                                 break;
291                         case 0xff82:
292                                 // display ctrl register
293                                 dispctrl = data;
294                                 update_bank();
295                                 break;
296                         case 0xff83:
297                                 // page select register
298                                 pagesel = data;
299                                 update_bank();
300                                 break;
301                         case 0xff88:
302                                 // access start register
303                                 accaddr = (accaddr & 0xff) | ((data & 0x7f) << 8);
304                                 break;
305                         case 0xff89:
306                                 // access start register
307                                 accaddr = (accaddr & 0xff00) | (data & 0xfe);
308                                 break;
309                         case 0xff8a:
310                                 // display start register
311                                 dispaddr = (dispaddr & 0xff) | ((data & 0x7f) << 8);
312                                 break;
313                         case 0xff8b:
314                                 // display start register
315                                 dispaddr = (dispaddr & 0xff00) | (data & 0xfe);
316                                 break;
317                         case 0xff8e:
318                                 // crtc addr register
319                                 d_crtc->write_io8(0, data);
320                                 break;
321                         case 0xff8f:
322                                 // crtc data register
323                                 d_crtc->write_io8(1, data);
324                                 break;
325                         case 0xff94:
326                                 kj_h = data & 0x7f;
327                                 break;
328                         case 0xff95:
329                                 kj_l = data & 0x7f;
330                                 kj_row = 0;
331                                 if(kj_h < 0x30) {
332                                         kj_ofs = (((kj_l - 0x00) & 0x1f) <<  5) | (((kj_l - 0x20) & 0x20) <<  9) | (((kj_l - 0x20) & 0x40) <<  7) | (((kj_h - 0x00) & 0x07) << 10);
333                                 } else if(kj_h < 0x70) {
334                                         kj_ofs = (((kj_l - 0x00) & 0x1f) <<  5) + (((kj_l - 0x20) & 0x60) <<  9) + (((kj_h - 0x00) & 0x0f) << 10) + (((kj_h - 0x30) & 0x70) * 0xc00) + 0x08000;
335                                 } else {
336                                         kj_ofs = (((kj_l - 0x00) & 0x1f) <<  5) | (((kj_l - 0x20) & 0x20) <<  9) | (((kj_l - 0x20) & 0x40) <<  7) | (((kj_h - 0x00) & 0x07) << 10) | 0x38000;
337                                 }
338                                 break;
339                         case 0xff96:
340                                 kanji16[(kj_ofs | ((kj_row & 0xf) << 1)) & 0x3ffff] = data;
341                                 break;
342                         case 0xff97:
343                                 kanji16[(kj_ofs | ((kj_row++ & 0xf) << 1) | 1) & 0x3ffff] = data;
344                                 break;
345                         case 0xff99:
346                                 ankcg = data;
347                                 update_bank();
348                                 break;
349                         case 0xffa0:
350                                 cmdreg = data;
351                                 break;
352                         case 0xffa1:
353                                 imgcol = data;
354                                 break;
355                         case 0xffa2:
356                                 maskreg = data;
357                                 break;
358                         case 0xffa3:
359                         case 0xffa4:
360                         case 0xffa5:
361                         case 0xffa6:
362                         case 0xffa7:
363                         case 0xffa8:
364                         case 0xffa9:
365                         case 0xffaa:
366                                 compreg[addr & 7] = data;
367                                 break;
368                         case 0xffab:
369                                 bankdis = data;
370                                 break;
371                         case 0xffac:
372                         case 0xffad:
373                         case 0xffae:
374                         case 0xffaf:
375                                 tilereg[addr & 3] = data;
376                                 break;
377                         case 0xffb0:
378                                 lofs = (lofs & 0xff) | (data << 8);
379                                 break;
380                         case 0xffb1:
381                                 lofs = (lofs & 0xff00) | data;
382                                 break;
383                         case 0xffb2:
384                                 lsty = (lsty & 0xff) | (data << 8);
385                                 break;
386                         case 0xffb3:
387                                 lsty = (lsty & 0xff00) | data;
388                                 break;
389                         case 0xffb4:
390                                 lsx = (lsx & 0xff) | (data << 8);
391                                 break;
392                         case 0xffb5:
393                                 lsx = (lsx & 0xff00) | data;
394                                 break;
395                         case 0xffb6:
396                                 lsy = (lsy & 0xff) | (data << 8);
397                                 break;
398                         case 0xffb7:
399                                 lsy = (lsy & 0xff00) | data;
400                                 break;
401                         case 0xffb8:
402                                 lex = (lex & 0xff) | (data << 8);
403                                 break;
404                         case 0xffb9:
405                                 lex = (lex & 0xff00) | data;
406                                 break;
407                         case 0xffba:
408                                 ley = (ley & 0xff) | (data << 8);
409                                 break;
410                         case 0xffbb:
411                                 ley = (ley & 0xff00) | data;
412                                 // start drawing line
413                                 line();
414                                 break;
415                         }
416                         return;
417                 }
418 #endif
419         }
420         if((addr & ~3) == 8 && (protect & 0x80)) {
421                 return;
422         }
423         wbank[addr >> 11][addr & 0x7ff] = data;
424 }
425
426 uint32_t MEMORY::read_data8(uint32_t addr)
427 {
428         if(addr & 0xff000000) {
429                 // > 16MB
430                 if(addr >= 0xffffc000) {
431                         return ipl[addr & 0x3fff];
432                 }
433                 return 0xff;
434         }
435 #ifndef _FMR60
436         if(!mainmem) {
437                 if(0xcff80 <= addr && addr < 0xcffe0) {
438 #ifdef _DEBUG_LOG
439 //                      this->out_debug_log(_T("MR\t%4x\n"), addr);
440 #endif
441                         // memory mapped i/o
442                         switch(addr & 0xffff) {
443                         case 0xff80:
444                                 // mix register
445                                 return mix;
446                         case 0xff81:
447                                 // update register
448                                 return wplane | (rplane << 6);
449                         case 0xff83:
450                                 // page select register
451                                 return pagesel;
452                         case 0xff86:
453                                 // status register
454                                 return (disp ? 0x80 : 0) | (vsync ? 4 : 0) | 0x10;
455                         case 0xff8e:
456                                 // crtc addr register
457                                 return d_crtc->read_io8(0);
458                         case 0xff8f:
459                                 // crtc data register
460                                 return d_crtc->read_io8(1);
461                         case 0xff94:
462                                 return 0x80;    // ???
463                         case 0xff96:
464                                 return kanji16[(kj_ofs | ((kj_row & 0xf) << 1)) & 0x3ffff];
465                         case 0xff97:
466                                 return kanji16[(kj_ofs | ((kj_row++ & 0xf) << 1) | 1) & 0x3ffff];
467                         case 0xffa0:
468                                 return cmdreg;
469                         case 0xffa1:
470                                 return imgcol | 0xf0;
471                         case 0xffa2:
472                                 return maskreg;
473                         case 0xffa3:
474                                 return compbit;
475                         case 0xffab:
476                                 return bankdis & 0xf;
477                         }
478                         return 0xff;
479                 }
480         }
481 #endif
482         return rbank[addr >> 11][addr & 0x7ff];
483 }
484
485 void MEMORY::write_dma_data8(uint32_t addr, uint32_t data)
486 {
487         write_data8(addr & dma_addr_mask, data);
488 }
489
490 uint32_t MEMORY::read_dma_data8(uint32_t addr)
491 {
492         return read_data8(addr & dma_addr_mask);
493 }
494
495 void MEMORY::write_io8(uint32_t addr, uint32_t data)
496 {
497         switch(addr & 0xffff) {
498         case 0x20:
499                 // protect and reset
500                 protect = data;
501                 update_bank();
502                 if(data & 0x40) {
503                         // power off
504                         emu->power_off();
505                 }
506                 if(data & 1) {
507                         // software reset
508                         rst |= 1;
509                         d_cpu->reset();
510                 }
511                 // protect mode
512 #if defined(HAS_I286)
513                 if(data & 0x20) {
514                         d_cpu->set_address_mask(0x00ffffff);
515                 } else {
516                         d_cpu->set_address_mask(0x000fffff);
517                 }
518 #else
519                 switch(data & 0x30) {
520                 case 0x00:      // 20bit
521                         d_cpu->set_address_mask(0x000fffff);
522                         break;
523                 case 0x20:      // 24bit
524                         d_cpu->set_address_mask(0x00ffffff);
525                         break;
526                 default:        // 32bit
527                         d_cpu->set_address_mask(0xffffffff);
528                         break;
529                 }
530 #endif
531                 update_dma_addr_mask();
532                 break;
533         case 0x22:
534                 dma_addr_reg = data;
535                 update_dma_addr_mask();
536                 break;
537         case 0x24:
538                 dma_wrap_reg = data;
539                 update_dma_addr_mask();
540                 break;
541         case 0x400:
542                 // video output control
543                 break;
544         case 0x402:
545                 // update register
546                 wplane = data & 0xf;
547                 break;
548         case 0x404:
549                 // read out register
550                 mainmem = data & 0x80;
551                 rplane = data & 3;
552                 update_bank();
553                 break;
554         case 0x408:
555                 // palette code register
556                 apalsel = data & 0xf;
557                 break;
558         case 0x40a:
559                 // blue level register
560                 apal[apalsel][0] = data & 0xf0;
561                 palette_cg[apalsel] = RGB_COLOR(apal[apalsel][1], apal[apalsel][2], apal[apalsel][0]);
562                 break;
563         case 0x40c:
564                 // red level register
565                 apal[apalsel][1] = data & 0xf0;
566                 palette_cg[apalsel] = RGB_COLOR(apal[apalsel][1], apal[apalsel][2], apal[apalsel][0]);
567                 break;
568         case 0x40e:
569                 // green level register
570                 apal[apalsel][2] = data & 0xf0;
571                 palette_cg[apalsel] = RGB_COLOR(apal[apalsel][1], apal[apalsel][2], apal[apalsel][0]);
572                 break;
573         case 0xfd98:
574         case 0xfd99:
575         case 0xfd9a:
576         case 0xfd9b:
577         case 0xfd9c:
578         case 0xfd9d:
579         case 0xfd9e:
580         case 0xfd9f:
581                 // digital palette
582                 dpal[addr & 7] = data;
583                 if(data & 8) {
584                         palette_cg[addr & 7] = RGB_COLOR(data & 2 ? 255 : 0, data & 4 ? 255 : 0, data & 1 ? 255 : 0);
585                 } else {
586                         palette_cg[addr & 7] = RGB_COLOR(data & 2 ? 127 : 0, data & 4 ? 127 : 0, data & 1 ? 127 : 0);
587                 }
588                 break;
589         case 0xfda0:
590                 // video output control
591                 outctrl = data;
592                 break;
593         }
594 }
595
596 uint32_t MEMORY::read_io8(uint32_t addr)
597 {
598         uint32_t val = 0xff;
599         
600         switch(addr & 0xffff) {
601         case 0x20:
602                 // reset cause register
603                 val = rst | (d_cpu->get_shutdown_flag() << 1);
604                 rst = 0;
605                 d_cpu->set_shutdown_flag(0);
606                 return val | 0x7c;
607         case 0x21:
608 //              return 0x1f;
609                 return 0xdf;
610         case 0x24:
611                 return dma_wrap_reg;
612         case 0x30:
613                 // machine & cpu id
614                 return machine_id;
615         case 0x400:
616                 // system status register
617 #ifdef _FMR60
618                 return 0xff;
619 #else
620                 return 0xfe;
621 //              return 0xf6;
622 #endif
623         case 0x402:
624                 // update register
625                 return wplane | 0xf0;
626         case 0x404:
627                 // read out register
628                 return mainmem | rplane | 0x7c;
629         case 0x40a:
630                 // blue level register
631                 return apal[apalsel][0];
632         case 0x40c:
633                 // red level register
634                 return apal[apalsel][1];
635         case 0x40e:
636                 // green level register
637                 return apal[apalsel][2];
638         case 0xfd98:
639         case 0xfd99:
640         case 0xfd9a:
641         case 0xfd9b:
642         case 0xfd9c:
643         case 0xfd9d:
644         case 0xfd9e:
645         case 0xfd9f:
646                 // digital palette
647                 return dpal[addr & 7] | 0xf0;
648         case 0xfda0:
649                 // status register
650                 return (disp ? 2 : 0) | (vsync ? 1 : 0) | 0xfc;
651         }
652         return 0xff;
653 }
654
655 void MEMORY::write_signal(int id, uint32_t data, uint32_t mask)
656 {
657         if(id == SIG_MEMORY_DISP) {
658                 disp = ((data & mask) != 0);
659         } else if(id == SIG_MEMORY_VSYNC) {
660                 vsync = ((data & mask) != 0);
661         }
662 }
663
664 void MEMORY::event_frame()
665 {
666         blink++;
667 }
668
669 void MEMORY::update_bank()
670 {
671         if(!mainmem) {
672 #ifdef _FMR60
673                 int ofs = rplane * 0x20000;
674                 SET_BANK(0xc0000, 0xdffff, vram + ofs, vram + ofs);
675                 SET_BANK(0xe0000, 0xeffff, wdmy, rdmy);
676 #else
677                 if(dispctrl & 0x40) {
678                         // 400 line
679                         int ofs = (rplane | ((pagesel >> 2) & 4)) * 0x8000;
680                         SET_BANK(0xc0000, 0xc7fff, vram + ofs, vram + ofs);
681                 } else {
682                         // 200 line
683                         int ofs = (rplane | ((pagesel >> 1) & 0xc)) * 0x4000;
684                         SET_BANK(0xc0000, 0xc3fff, vram + ofs, vram + ofs);
685                         SET_BANK(0xc4000, 0xc7fff, vram + ofs, vram + ofs);
686                 }
687                 SET_BANK(0xc8000, 0xc8fff, cvram, cvram);
688                 SET_BANK(0xc9000, 0xc9fff, wdmy, rdmy);
689                 if(ankcg & 1) {
690                         SET_BANK(0xca000, 0xca7ff, wdmy, ank8);
691                         SET_BANK(0xca800, 0xcafff, wdmy, rdmy);
692                         SET_BANK(0xcb000, 0xcbfff, wdmy, ank16);
693                 } else {
694                         SET_BANK(0xca000, 0xcafff, kvram, kvram);
695                         SET_BANK(0xcb000, 0xcbfff, wdmy, rdmy);
696                 }
697                 SET_BANK(0xcc000, 0xeffff, wdmy, rdmy);
698 #endif
699         } else {
700                 SET_BANK(0xc0000, 0xeffff, ram + 0xc0000, ram + 0xc0000);
701         }
702         if(!(protect & 0x20)) {
703 #ifdef _FMR60
704                 SET_BANK(0xf8000, 0xf9fff, cvram, cvram);
705                 SET_BANK(0xfa000, 0xfbfff, avram, avram);
706 #else
707                 SET_BANK(0xf8000, 0xfbfff, wdmy, rdmy);
708 #endif
709                 SET_BANK(0xfc000, 0xfffff, wdmy, ipl);
710         } else {
711                 SET_BANK(0xf8000, 0xfffff, ram + 0xf8000, ram + 0xf8000);
712         }
713 }
714
715 void MEMORY::update_dma_addr_mask()
716 {
717         switch(dma_addr_reg & 3) {
718         case 0:
719                 dma_addr_mask = d_cpu->get_address_mask();
720                 break;
721         case 1:
722                 if(!(dma_wrap_reg & 1) && d_cpu->get_address_mask() == 0x000fffff) {
723                         dma_addr_mask = 0x000fffff;
724                 } else {
725                         dma_addr_mask = 0x00ffffff;
726                 }
727                 break;
728         default:
729                 if(!(dma_wrap_reg & 1) && d_cpu->get_address_mask() == 0x000fffff) {
730                         dma_addr_mask = 0x000fffff;
731                 } else {
732                         dma_addr_mask = 0xffffffff;
733                 }
734                 break;
735         }
736 }
737
738 #ifndef _FMR60
739 void MEMORY::point(int x, int y, int col)
740 {
741         if(x < 640 && y < 400) {
742                 int ofs = ((lofs & 0x3fff) + (x >> 3) + y * 80) & 0x7fff;
743                 uint8_t bit = 0x80 >> (x & 7);
744                 for(int pl = 0; pl < 4; pl++) {
745                         uint8_t pbit = 1 << pl;
746                         if(!(bankdis & pbit)) {
747                                 if(col & pbit) {
748                                         vram[0x8000 * pl + ofs] |= bit;
749                                 } else {
750                                         vram[0x8000 * pl + ofs] &= ~bit;
751                                 }
752                         }
753                 }
754         }
755 }
756
757 void MEMORY::line()
758 {
759         int nx = lsx, ny = lsy;
760         int dx = abs(lex - lsx) * 2;
761         int dy = abs(ley - lsy) * 2;
762         int sx = (lex < lsx) ? -1 : 1;
763         int sy = (ley < lsy) ? -1 : 1;
764         int c = 0;
765         
766         point(lsx, lsy, (lsty & (0x8000 >> (c++ & 15))) ? imgcol : 0);
767         if(dx > dy) {
768                 int frac = dy - dx / 2;
769                 while(nx != lex) {
770                         if(frac >= 0) {
771                                 ny += sy;
772                                 frac -= dx;
773                         }
774                         nx += sx;
775                         frac += dy;
776                         point(nx, ny, (lsty & (0x8000 >> (c++ & 15))) ? imgcol : 0);
777                 }
778         } else {
779                 int frac = dx - dy / 2;
780                 while(ny != ley) {
781                         if(frac >= 0) {
782                                 nx += sx;
783                                 frac -= dy;
784                         }
785                         ny += sy;
786                         frac += dx;
787                         point(nx, ny, (lsty & (0x8000 >> (c++ & 15))) ? imgcol : 0);
788                 }
789         }
790 //      point(lex, ley, (lsty & (0x8000 >> (c++ & 15))) ? imgcol : 0);
791 }
792 #endif
793
794 void MEMORY::draw_screen()
795 {
796         // render screen
797         memset(screen_txt, 0, sizeof(screen_txt));
798         memset(screen_cg, 0, sizeof(screen_cg));
799         if(outctrl & 1) {
800 #ifdef _FMR60
801                 draw_text();
802 #else
803                 if(mix & 8) {
804                         draw_text80();
805                 } else {
806                         draw_text40();
807                 }
808 #endif
809         }
810         if(outctrl & 4) {
811                 draw_cg();
812         }
813         
814         for(int y = 0; y < SCREEN_HEIGHT; y++) {
815                 scrntype_t* dest = emu->get_screen_buffer(y);
816                 uint8_t* txt = screen_txt[y];
817                 uint8_t* cg = screen_cg[y];
818                 
819                 for(int x = 0; x < SCREEN_WIDTH; x++) {
820                         dest[x] = txt[x] ? palette_txt[txt[x] & 15] : palette_cg[cg[x]];
821                 }
822         }
823         emu->screen_skip_line(false);
824 }
825
826 #ifdef _FMR60
827 void MEMORY::draw_text()
828 {
829         int src = ((chreg[12] << 9) | (chreg[13] << 1)) & 0x1fff;
830         int caddr = ((chreg[8] & 0xc0) == 0xc0) ? -1 : (((chreg[14] << 9) | (chreg[15] << 1)) & 0x1fff);
831         int ymax = (chreg[6] > 0) ? chreg[6] : 25;
832         int yofs = 750 / ymax;
833         
834         for(int y = 0; y < 25; y++) {
835                 for(int x = 0; x < 80; x++) {
836                         bool cursor = ((src >> 1) == caddr);
837                         int cx = x;
838                         uint8_t codel = cvram[src];
839                         uint8_t attrl = avram[src];
840                         src = (src + 1) & 0x1ffff;
841                         uint8_t codeh = cvram[src];
842                         uint8_t attrh = avram[src];
843                         src = (src + 1) & 0x1ffff;
844                         uint8_t col = (attrl & 15) | 16;
845                         bool blnk = (attrh & 0x40) || ((blink & 32) && (attrh & 0x10));
846                         bool rev = ((attrh & 8) != 0);
847                         uint8_t xor_mask = (rev != blnk) ? 0xff : 0;
848                         
849                         if(codeh & 0x80) {
850                                 // kanji
851                                 int ofs = (codel | ((codeh & 0x7f) << 8)) * 72;
852                                 for(int l = 3; l < 27 && l < yofs; l++) {
853                                         uint8_t pat0 = kanji24[ofs++] ^ xor_mask;
854                                         uint8_t pat1 = kanji24[ofs++] ^ xor_mask;
855                                         uint8_t pat2 = kanji24[ofs++] ^ xor_mask;
856                                         int yy = y * yofs + l;
857                                         if(yy >= 750) {
858                                                 break;
859                                         }
860                                         uint8_t* d = &screen_txt[yy][x * 14];
861                                         
862                                         d[ 2] = (pat0 & 0x80) ? col : 0;
863                                         d[ 3] = (pat0 & 0x40) ? col : 0;
864                                         d[ 4] = (pat0 & 0x20) ? col : 0;
865                                         d[ 5] = (pat0 & 0x10) ? col : 0;
866                                         d[ 6] = (pat0 & 0x08) ? col : 0;
867                                         d[ 7] = (pat0 & 0x04) ? col : 0;
868                                         d[ 8] = (pat0 & 0x02) ? col : 0;
869                                         d[ 9] = (pat0 & 0x01) ? col : 0;
870                                         d[10] = (pat1 & 0x80) ? col : 0;
871                                         d[11] = (pat1 & 0x40) ? col : 0;
872                                         d[12] = (pat1 & 0x20) ? col : 0;
873                                         d[13] = (pat1 & 0x10) ? col : 0;
874                                         d[14] = (pat1 & 0x08) ? col : 0;
875                                         d[15] = (pat1 & 0x04) ? col : 0;
876                                         d[16] = (pat1 & 0x02) ? col : 0;
877                                         d[17] = (pat1 & 0x01) ? col : 0;
878                                         d[18] = (pat2 & 0x80) ? col : 0;
879                                         d[19] = (pat2 & 0x40) ? col : 0;
880                                         d[20] = (pat2 & 0x20) ? col : 0;
881                                         d[21] = (pat2 & 0x10) ? col : 0;
882                                         d[22] = (pat2 & 0x08) ? col : 0;
883                                         d[23] = (pat2 & 0x04) ? col : 0;
884                                         d[24] = (pat2 & 0x02) ? col : 0;
885                                         d[25] = (pat2 & 0x01) ? col : 0;
886                                 }
887                                 src = (src + 2) & 0x1fff;
888                                 x++;
889                         } else if(codeh) {
890                         } else {
891                                 // ank
892                                 int ofs = codel * 48;
893                                 for(int l = 3; l < 27 && l < yofs; l++) {
894                                         uint8_t pat0 = ank24[ofs++] ^ xor_mask;
895                                         uint8_t pat1 = ank24[ofs++] ^ xor_mask;
896                                         int yy = y * yofs + l;
897                                         if(yy >= 750) {
898                                                 break;
899                                         }
900                                         uint8_t* d = &screen_txt[yy][x * 14];
901                                         
902                                         d[ 0] = (pat0 & 0x80) ? col : 0;
903                                         d[ 1] = (pat0 & 0x40) ? col : 0;
904                                         d[ 2] = (pat0 & 0x20) ? col : 0;
905                                         d[ 3] = (pat0 & 0x10) ? col : 0;
906                                         d[ 4] = (pat0 & 0x08) ? col : 0;
907                                         d[ 5] = (pat0 & 0x04) ? col : 0;
908                                         d[ 6] = (pat0 & 0x02) ? col : 0;
909                                         d[ 7] = (pat0 & 0x01) ? col : 0;
910                                         d[ 8] = (pat1 & 0x80) ? col : 0;
911                                         d[ 9] = (pat1 & 0x40) ? col : 0;
912                                         d[10] = (pat1 & 0x20) ? col : 0;
913                                         d[11] = (pat1 & 0x10) ? col : 0;
914                                         d[12] = (pat1 & 0x08) ? col : 0;
915                                         d[13] = (pat1 & 0x04) ? col : 0;
916                                 }
917                         }
918 /*
919                         if(cursor) {
920                                 int bp = chreg[10] & 0x60;
921                                 if(bp == 0 || (bp == 0x40 && (blink & 8)) || (bp == 0x60 && (blink & 0x10))) {
922                                         int st = chreg[10] & 15;
923                                         int ed = chreg[11] & 15;
924                                         for(int i = st; i < ed && i < yofs; i++) {
925                                                 memset(&screen_txt[y * yofs + i][cx << 3], 7, 8);
926                                         }
927                                 }
928                         }
929 */
930                 }
931         }
932 }
933 #else
934 void MEMORY::draw_text40()
935 {
936         int src = ((chreg[12] << 9) | (chreg[13] << 1)) & 0xfff;
937         int caddr = ((chreg[8] & 0xc0) == 0xc0) ? -1 : (((chreg[14] << 9) | (chreg[15] << 1) | (mix & 0x20 ? 1 : 0)) & 0x7ff);
938         int ymax = (chreg[6] > 0) ? chreg[6] : 25;
939         int yofs = 400 / ymax;
940         
941         for(int y = 0; y < ymax; y++) {
942                 for(int x = 0; x < 40; x++) {
943                         bool cursor = ((src >> 1) == caddr);
944                         int cx = x;
945                         uint8_t code = cvram[src];
946                         uint8_t h = kvram[src] & 0x7f;
947                         src = (src + 1) & 0xfff;
948                         uint8_t attr = cvram[src];
949                         uint8_t l = kvram[src] & 0x7f;
950                         src = (src + 1) & 0xfff;
951                         uint8_t col = ((attr & 0x20) >> 2) | (attr & 7) | 16;
952                         bool blnk = (blink & 32) && (attr & 0x10);
953                         bool rev = ((attr & 8) != 0);
954                         uint8_t xor_mask = (rev != blnk) ? 0xff : 0;
955                         
956                         if(attr & 0x40) {
957                                 // kanji
958                                 int ofs;
959                                 if(h < 0x30) {
960                                         ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10);
961                                 } else if(h < 0x70) {
962                                         ofs = (((l - 0x00) & 0x1f) <<  5) + (((l - 0x20) & 0x60) <<  9) + (((h - 0x00) & 0x0f) << 10) + (((h - 0x30) & 0x70) * 0xc00) + 0x08000;
963                                 } else {
964                                         ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10) | 0x38000;
965                                 }
966                                 
967                                 for(int l = 0; l < 16 && l < yofs; l++) {
968                                         uint8_t pat0 = kanji16[ofs + (l << 1) + 0] ^ xor_mask;
969                                         uint8_t pat1 = kanji16[ofs + (l << 1) + 1] ^ xor_mask;
970                                         int yy = y * yofs + l;
971                                         if(yy >= 400) {
972                                                 break;
973                                         }
974                                         uint8_t* d = &screen_txt[yy][x << 4];
975                                         
976                                         d[ 0] = d[ 1] = (pat0 & 0x80) ? col : 0;
977                                         d[ 2] = d[ 3] = (pat0 & 0x40) ? col : 0;
978                                         d[ 4] = d[ 5] = (pat0 & 0x20) ? col : 0;
979                                         d[ 6] = d[ 7] = (pat0 & 0x10) ? col : 0;
980                                         d[ 8] = d[ 9] = (pat0 & 0x08) ? col : 0;
981                                         d[10] = d[11] = (pat0 & 0x04) ? col : 0;
982                                         d[12] = d[13] = (pat0 & 0x02) ? col : 0;
983                                         d[14] = d[15] = (pat0 & 0x01) ? col : 0;
984                                         d[16] = d[17] = (pat1 & 0x80) ? col : 0;
985                                         d[18] = d[19] = (pat1 & 0x40) ? col : 0;
986                                         d[20] = d[21] = (pat1 & 0x20) ? col : 0;
987                                         d[22] = d[23] = (pat1 & 0x10) ? col : 0;
988                                         d[24] = d[25] = (pat1 & 0x08) ? col : 0;
989                                         d[26] = d[27] = (pat1 & 0x04) ? col : 0;
990                                         d[28] = d[29] = (pat1 & 0x02) ? col : 0;
991                                         d[30] = d[31] = (pat1 & 0x01) ? col : 0;
992                                 }
993                                 src = (src + 2) & 0xfff;
994                                 x++;
995                         } else {
996                                 for(int l = 0; l < 16 && l < yofs; l++) {
997                                         uint8_t pat = ank16[(code << 4) + l] ^ xor_mask;
998                                         int yy = y * yofs + l;
999                                         if(yy >= 400) {
1000                                                 break;
1001                                         }
1002                                         uint8_t* d = &screen_txt[yy][x << 4];
1003                                         
1004                                         d[ 0] = d[ 1] = (pat & 0x80) ? col : 0;
1005                                         d[ 2] = d[ 3] = (pat & 0x40) ? col : 0;
1006                                         d[ 4] = d[ 5] = (pat & 0x20) ? col : 0;
1007                                         d[ 6] = d[ 7] = (pat & 0x10) ? col : 0;
1008                                         d[ 8] = d[ 9] = (pat & 0x08) ? col : 0;
1009                                         d[10] = d[11] = (pat & 0x04) ? col : 0;
1010                                         d[12] = d[13] = (pat & 0x02) ? col : 0;
1011                                         d[14] = d[15] = (pat & 0x01) ? col : 0;
1012                                 }
1013                         }
1014                         if(cursor) {
1015                                 int bp = chreg[10] & 0x60;
1016                                 if(bp == 0 || (bp == 0x40 && (blink & 8)) || (bp == 0x60 && (blink & 0x10))) {
1017                                         int st = chreg[10] & 15;
1018                                         int ed = chreg[11] & 15;
1019                                         for(int i = st; i < ed && i < yofs; i++) {
1020                                                 memset(&screen_txt[y * yofs + i][cx << 3], 7, 8);
1021                                         }
1022                                 }
1023                         }
1024                 }
1025         }
1026 }
1027
1028 void MEMORY::draw_text80()
1029 {
1030         int src = ((chreg[12] << 9) | (chreg[13] << 1)) & 0xfff;
1031         int caddr = ((chreg[8] & 0xc0) == 0xc0) ? -1 : (((chreg[14] << 9) | (chreg[15] << 1) | (mix & 0x20 ? 1 : 0)) & 0x7ff);
1032         int ymax = (chreg[6] > 0) ? chreg[6] : 25;
1033         int yofs = 400 / ymax;
1034         
1035         for(int y = 0; y < 25; y++) {
1036                 for(int x = 0; x < 80; x++) {
1037                         bool cursor = ((src >> 1) == caddr);
1038                         int cx = x;
1039                         uint8_t code = cvram[src];
1040                         uint8_t h = kvram[src] & 0x7f;
1041                         src = (src + 1) & 0xfff;
1042                         uint8_t attr = cvram[src];
1043                         uint8_t l = kvram[src] & 0x7f;
1044                         src = (src + 1) & 0xfff;
1045                         uint8_t col = ((attr & 0x20) >> 2) | (attr & 7) | 16;
1046                         bool blnk = (blink & 32) && (attr & 0x10);
1047                         bool rev = ((attr & 8) != 0);
1048                         uint8_t xor_mask = (rev != blnk) ? 0xff : 0;
1049                         
1050                         if(attr & 0x40) {
1051                                 // kanji
1052                                 int ofs;
1053                                 if(h < 0x30) {
1054                                         ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10);
1055                                 } else if(h < 0x70) {
1056                                         ofs = (((l - 0x00) & 0x1f) <<  5) + (((l - 0x20) & 0x60) <<  9) + (((h - 0x00) & 0x0f) << 10) + (((h - 0x30) & 0x70) * 0xc00) + 0x08000;
1057                                 } else {
1058                                         ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10) | 0x38000;
1059                                 }
1060                                 
1061                                 for(int l = 0; l < 16 && l < yofs; l++) {
1062                                         uint8_t pat0 = kanji16[ofs + (l << 1) + 0] ^ xor_mask;
1063                                         uint8_t pat1 = kanji16[ofs + (l << 1) + 1] ^ xor_mask;
1064                                         int yy = y * yofs + l;
1065                                         if(yy >= 400) {
1066                                                 break;
1067                                         }
1068                                         uint8_t* d = &screen_txt[yy][x << 3];
1069                                         
1070                                         d[ 0] = (pat0 & 0x80) ? col : 0;
1071                                         d[ 1] = (pat0 & 0x40) ? col : 0;
1072                                         d[ 2] = (pat0 & 0x20) ? col : 0;
1073                                         d[ 3] = (pat0 & 0x10) ? col : 0;
1074                                         d[ 4] = (pat0 & 0x08) ? col : 0;
1075                                         d[ 5] = (pat0 & 0x04) ? col : 0;
1076                                         d[ 6] = (pat0 & 0x02) ? col : 0;
1077                                         d[ 7] = (pat0 & 0x01) ? col : 0;
1078                                         d[ 8] = (pat1 & 0x80) ? col : 0;
1079                                         d[ 9] = (pat1 & 0x40) ? col : 0;
1080                                         d[10] = (pat1 & 0x20) ? col : 0;
1081                                         d[11] = (pat1 & 0x10) ? col : 0;
1082                                         d[12] = (pat1 & 0x08) ? col : 0;
1083                                         d[13] = (pat1 & 0x04) ? col : 0;
1084                                         d[14] = (pat1 & 0x02) ? col : 0;
1085                                         d[15] = (pat1 & 0x01) ? col : 0;
1086                                 }
1087                                 src = (src + 2) & 0xfff;
1088                                 x++;
1089                         } else {
1090                                 for(int l = 0; l < 16 && l < yofs; l++) {
1091                                         uint8_t pat = ank16[(code << 4) + l] ^ xor_mask;
1092                                         int yy = y * yofs + l;
1093                                         if(yy >= 400) {
1094                                                 break;
1095                                         }
1096                                         uint8_t* d = &screen_txt[yy][x << 3];
1097                                         
1098                                         d[0] = (pat & 0x80) ? col : 0;
1099                                         d[1] = (pat & 0x40) ? col : 0;
1100                                         d[2] = (pat & 0x20) ? col : 0;
1101                                         d[3] = (pat & 0x10) ? col : 0;
1102                                         d[4] = (pat & 0x08) ? col : 0;
1103                                         d[5] = (pat & 0x04) ? col : 0;
1104                                         d[6] = (pat & 0x02) ? col : 0;
1105                                         d[7] = (pat & 0x01) ? col : 0;
1106                                 }
1107                         }
1108                         if(cursor) {
1109                                 int bp = chreg[10] & 0x60;
1110                                 if(bp == 0 || (bp == 0x40 && (blink & 8)) || (bp == 0x60 && (blink & 0x10))) {
1111                                         int st = chreg[10] & 15;
1112                                         int ed = chreg[11] & 15;
1113                                         for(int i = st; i < ed && i < yofs; i++) {
1114                                                 memset(&screen_txt[y * yofs + i][cx << 3], 7, 8);
1115                                         }
1116                                 }
1117                         }
1118                 }
1119         }
1120 }
1121 #endif
1122
1123 void MEMORY::draw_cg()
1124 {
1125 #ifdef _FMR60
1126         uint8_t* p0 = &vram[0x00000];
1127         uint8_t* p1 = &vram[0x20000];
1128         uint8_t* p2 = &vram[0x40000];
1129         uint8_t* p3 = &vram[0x60000];
1130         int ptr = 0;
1131         
1132         for(int y = 0; y < 750; y++) {
1133                 for(int x = 0; x < 1120; x += 8) {
1134                         uint8_t r = p0[ptr];
1135                         uint8_t g = p1[ptr];
1136                         uint8_t b = p2[ptr];
1137                         uint8_t i = p3[ptr++];
1138                         ptr &= 0x1ffff;
1139                         uint8_t* d = &screen_cg[y][x];
1140                         
1141                         d[0] = ((r & 0x80) >> 7) | ((g & 0x80) >> 6) | ((b & 0x80) >> 5) | ((i & 0x80) >> 4);
1142                         d[1] = ((r & 0x40) >> 6) | ((g & 0x40) >> 5) | ((b & 0x40) >> 4) | ((i & 0x40) >> 3);
1143                         d[2] = ((r & 0x20) >> 5) | ((g & 0x20) >> 4) | ((b & 0x20) >> 3) | ((i & 0x20) >> 2);
1144                         d[3] = ((r & 0x10) >> 4) | ((g & 0x10) >> 3) | ((b & 0x10) >> 2) | ((i & 0x10) >> 1);
1145                         d[4] = ((r & 0x08) >> 3) | ((g & 0x08) >> 2) | ((b & 0x08) >> 1) | ((i & 0x08) >> 0);
1146                         d[5] = ((r & 0x04) >> 2) | ((g & 0x04) >> 1) | ((b & 0x04) >> 0) | ((i & 0x04) << 1);
1147                         d[6] = ((r & 0x02) >> 1) | ((g & 0x02) >> 0) | ((b & 0x02) << 1) | ((i & 0x02) << 2);
1148                         d[7] = ((r & 0x01) >> 0) | ((g & 0x01) << 1) | ((b & 0x01) << 2) | ((i & 0x01) << 3);
1149                 }
1150         }
1151 #else
1152         if(dispctrl & 0x40) {
1153                 // 400line
1154                 int pofs = ((dispctrl >> 3) & 1) * 0x20000;
1155                 uint8_t* p0 = (dispctrl & 0x01) ? &vram[pofs | 0x00000] : dummy;
1156                 uint8_t* p1 = (dispctrl & 0x02) ? &vram[pofs | 0x08000] : dummy;
1157                 uint8_t* p2 = (dispctrl & 0x04) ? &vram[pofs | 0x10000] : dummy;
1158                 uint8_t* p3 = (dispctrl & 0x20) ? &vram[pofs | 0x18000] : dummy;        // ???
1159                 int ptr = dispaddr & 0x7ffe;
1160                 
1161                 for(int y = 0; y < 400; y++) {
1162                         for(int x = 0; x < 640; x += 8) {
1163                                 uint8_t r = p0[ptr];
1164                                 uint8_t g = p1[ptr];
1165                                 uint8_t b = p2[ptr];
1166                                 uint8_t i = p3[ptr++];
1167                                 ptr &= 0x7fff;
1168                                 uint8_t* d = &screen_cg[y][x];
1169                                 
1170                                 d[0] = ((r & 0x80) >> 7) | ((g & 0x80) >> 6) | ((b & 0x80) >> 5) | ((i & 0x80) >> 4);
1171                                 d[1] = ((r & 0x40) >> 6) | ((g & 0x40) >> 5) | ((b & 0x40) >> 4) | ((i & 0x40) >> 3);
1172                                 d[2] = ((r & 0x20) >> 5) | ((g & 0x20) >> 4) | ((b & 0x20) >> 3) | ((i & 0x20) >> 2);
1173                                 d[3] = ((r & 0x10) >> 4) | ((g & 0x10) >> 3) | ((b & 0x10) >> 2) | ((i & 0x10) >> 1);
1174                                 d[4] = ((r & 0x08) >> 3) | ((g & 0x08) >> 2) | ((b & 0x08) >> 1) | ((i & 0x08) >> 0);
1175                                 d[5] = ((r & 0x04) >> 2) | ((g & 0x04) >> 1) | ((b & 0x04) >> 0) | ((i & 0x04) << 1);
1176                                 d[6] = ((r & 0x02) >> 1) | ((g & 0x02) >> 0) | ((b & 0x02) << 1) | ((i & 0x02) << 2);
1177                                 d[7] = ((r & 0x01) >> 0) | ((g & 0x01) << 1) | ((b & 0x01) << 2) | ((i & 0x01) << 3);
1178                         }
1179                 }
1180         } else {
1181                 // 200line
1182                 int pofs = ((dispctrl >> 3) & 3) * 0x10000;
1183                 uint8_t* p0 = (dispctrl & 0x01) ? &vram[pofs | 0x0000] : dummy;
1184                 uint8_t* p1 = (dispctrl & 0x02) ? &vram[pofs | 0x4000] : dummy;
1185                 uint8_t* p2 = (dispctrl & 0x04) ? &vram[pofs | 0x8000] : dummy;
1186                 uint8_t* p3 = (dispctrl & 0x20) ? &vram[pofs | 0xc000] : dummy; // ???
1187                 int ptr = dispaddr & 0x3ffe;
1188                 
1189                 for(int y = 0; y < 400; y += 2) {
1190                         for(int x = 0; x < 640; x += 8) {
1191                                 uint8_t r = p0[ptr];
1192                                 uint8_t g = p1[ptr];
1193                                 uint8_t b = p2[ptr];
1194                                 uint8_t i = p3[ptr++];
1195                                 ptr &= 0x3fff;
1196                                 uint8_t* d = &screen_cg[y][x];
1197                                 
1198                                 d[0] = ((r & 0x80) >> 7) | ((g & 0x80) >> 6) | ((b & 0x80) >> 5) | ((i & 0x80) >> 4);
1199                                 d[1] = ((r & 0x40) >> 6) | ((g & 0x40) >> 5) | ((b & 0x40) >> 4) | ((i & 0x40) >> 3);
1200                                 d[2] = ((r & 0x20) >> 5) | ((g & 0x20) >> 4) | ((b & 0x20) >> 3) | ((i & 0x20) >> 2);
1201                                 d[3] = ((r & 0x10) >> 4) | ((g & 0x10) >> 3) | ((b & 0x10) >> 2) | ((i & 0x10) >> 1);
1202                                 d[4] = ((r & 0x08) >> 3) | ((g & 0x08) >> 2) | ((b & 0x08) >> 1) | ((i & 0x08) >> 0);
1203                                 d[5] = ((r & 0x04) >> 2) | ((g & 0x04) >> 1) | ((b & 0x04) >> 0) | ((i & 0x04) << 1);
1204                                 d[6] = ((r & 0x02) >> 1) | ((g & 0x02) >> 0) | ((b & 0x02) << 1) | ((i & 0x02) << 2);
1205                                 d[7] = ((r & 0x01) >> 0) | ((g & 0x01) << 1) | ((b & 0x01) << 2) | ((i & 0x01) << 3);
1206                         }
1207                         memcpy(screen_cg[y + 1], screen_cg[y], 640);
1208                 }
1209         }
1210 #endif
1211 }
1212
1213 #define STATE_VERSION   1
1214
1215 void MEMORY::save_state(FILEIO* state_fio)
1216 {
1217         state_fio->FputUint32(STATE_VERSION);
1218         state_fio->FputInt32(this_device_id);
1219         
1220         state_fio->Fwrite(ram, sizeof(ram), 1);
1221         state_fio->Fwrite(vram, sizeof(vram), 1);
1222         state_fio->Fwrite(cvram, sizeof(cvram), 1);
1223 #ifdef _FMR60
1224         state_fio->Fwrite(avram, sizeof(avram), 1);
1225 #else
1226         state_fio->Fwrite(kvram, sizeof(kvram), 1);
1227 #endif
1228         state_fio->FputUint8(machine_id);
1229         state_fio->FputUint8(protect);
1230         state_fio->FputUint8(rst);
1231         state_fio->FputUint8(mainmem);
1232         state_fio->FputUint8(rplane);
1233         state_fio->FputUint8(wplane);
1234         state_fio->FputUint8(dma_addr_reg);
1235         state_fio->FputUint8(dma_wrap_reg);
1236         state_fio->FputUint32(dma_addr_mask);
1237         state_fio->FputBool(disp);
1238         state_fio->FputBool(vsync);
1239         state_fio->FputInt32(blink);
1240         state_fio->Fwrite(apal, sizeof(apal), 1);
1241         state_fio->FputUint8(apalsel);
1242         state_fio->Fwrite(dpal, sizeof(dpal), 1);
1243         state_fio->FputUint8(outctrl);
1244 #ifndef _FMR60
1245         state_fio->FputUint8(pagesel);
1246         state_fio->FputUint8(ankcg);
1247         state_fio->FputUint8(dispctrl);
1248         state_fio->FputUint8(mix);
1249         state_fio->FputUint16(accaddr);
1250         state_fio->FputUint16(dispaddr);
1251         state_fio->FputInt32(kj_h);
1252         state_fio->FputInt32(kj_l);
1253         state_fio->FputInt32(kj_ofs);
1254         state_fio->FputInt32(kj_row);
1255         state_fio->FputUint8(cmdreg);
1256         state_fio->FputUint8(imgcol);
1257         state_fio->FputUint8(maskreg);
1258         state_fio->Fwrite(compreg, sizeof(compreg), 1);
1259         state_fio->FputUint8(compbit);
1260         state_fio->FputUint8(bankdis);
1261         state_fio->Fwrite(tilereg, sizeof(tilereg), 1);
1262         state_fio->FputUint16(lofs);
1263         state_fio->FputUint16(lsty);
1264         state_fio->FputUint16(lsx);
1265         state_fio->FputUint16(lsy);
1266         state_fio->FputUint16(lex);
1267         state_fio->FputUint16(ley);
1268 #endif
1269         state_fio->Fwrite(palette_cg, sizeof(palette_cg), 1);
1270 }
1271
1272 bool MEMORY::load_state(FILEIO* state_fio)
1273 {
1274         if(state_fio->FgetUint32() != STATE_VERSION) {
1275                 return false;
1276         }
1277         if(state_fio->FgetInt32() != this_device_id) {
1278                 return false;
1279         }
1280         state_fio->Fread(ram, sizeof(ram), 1);
1281         state_fio->Fread(vram, sizeof(vram), 1);
1282         state_fio->Fread(cvram, sizeof(cvram), 1);
1283 #ifdef _FMR60
1284         state_fio->Fread(avram, sizeof(avram), 1);
1285 #else
1286         state_fio->Fread(kvram, sizeof(kvram), 1);
1287 #endif
1288         machine_id = state_fio->FgetUint8();
1289         protect = state_fio->FgetUint8();
1290         rst = state_fio->FgetUint8();
1291         mainmem = state_fio->FgetUint8();
1292         rplane = state_fio->FgetUint8();
1293         wplane = state_fio->FgetUint8();
1294         dma_addr_reg = state_fio->FgetUint8();
1295         dma_wrap_reg = state_fio->FgetUint8();
1296         dma_addr_mask = state_fio->FgetUint32();
1297         disp = state_fio->FgetBool();
1298         vsync = state_fio->FgetBool();
1299         blink = state_fio->FgetInt32();
1300         state_fio->Fread(apal, sizeof(apal), 1);
1301         apalsel = state_fio->FgetUint8();
1302         state_fio->Fread(dpal, sizeof(dpal), 1);
1303         outctrl = state_fio->FgetUint8();
1304 #ifndef _FMR60
1305         pagesel = state_fio->FgetUint8();
1306         ankcg = state_fio->FgetUint8();
1307         dispctrl = state_fio->FgetUint8();
1308         mix = state_fio->FgetUint8();
1309         accaddr = state_fio->FgetUint16();
1310         dispaddr = state_fio->FgetUint16();
1311         kj_h = state_fio->FgetInt32();
1312         kj_l = state_fio->FgetInt32();
1313         kj_ofs = state_fio->FgetInt32();
1314         kj_row = state_fio->FgetInt32();
1315         cmdreg = state_fio->FgetUint8();
1316         imgcol = state_fio->FgetUint8();
1317         maskreg = state_fio->FgetUint8();
1318         state_fio->Fread(compreg, sizeof(compreg), 1);
1319         compbit = state_fio->FgetUint8();
1320         bankdis = state_fio->FgetUint8();
1321         state_fio->Fread(tilereg, sizeof(tilereg), 1);
1322         lofs = state_fio->FgetUint16();
1323         lsty = state_fio->FgetUint16();
1324         lsx = state_fio->FgetUint16();
1325         lsy = state_fio->FgetUint16();
1326         lex = state_fio->FgetUint16();
1327         ley = state_fio->FgetUint16();
1328 #endif
1329         state_fio->Fread(palette_cg, sizeof(palette_cg), 1);
1330         
1331         // post process
1332         update_bank();
1333         return true;
1334 }
1335