OSDN Git Service

[VM] Merge Upstream 2018-02-23.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm16beta / sub.cpp
1 /*
2         FUJITSU FM16beta Emulator 'eFM16beta'
3
4         Author : Takeda.Toshiya
5         Date   : 2017.12.28-
6
7         [ sub system ]
8 */
9
10 #include "sub.h"
11 #include "main.h"
12 #include "../pcm1bit.h"
13
14 void SUB::initialize()
15 {
16         MEMORY::initialize();
17
18         // init memory
19         memset(wram, 0, sizeof(wram));
20         memset(sram, 0, sizeof(sram));
21         memset(gvram, 0, sizeof(gvram));
22         memset(dummy, 0, sizeof(dummy));
23         memset(cvram, 0, sizeof(cvram));
24         memset(kvram, 0, sizeof(kvram));
25         memset(rom, 0xff, sizeof(rom));
26         memset(ank8, 0xff, sizeof(ank8));
27         memset(ank16, 0xff, sizeof(ank16));
28         memset(kanji16, 0xff, sizeof(kanji16));
29         
30         // load rom image
31         FILEIO* fio = new FILEIO();
32         if(fio->Fopen(create_local_path(_T("SUBSYS.ROM")), FILEIO_READ_BINARY) ||
33            fio->Fopen(create_local_path(_T("SUB.ROM")), FILEIO_READ_BINARY)) {
34                 fio->Fread(rom, sizeof(rom), 1);
35                 fio->Fclose();
36                 if(rom[0x4ff2] == 0xff && rom[0x4ff3] == 0xff) { // SWI3
37                         rom[0x4ff2] = 0x9f;
38                         rom[0x4ff3] = 0x6e;
39                 }
40                 if(rom[0x4ff4] == 0xff && rom[0x4ff5] == 0xff) { // SWI2
41                         rom[0x4ff4] = 0x9f;
42                         rom[0x4ff5] = 0x71;
43                 }
44                 if(rom[0x4ff6] == 0xff && rom[0x4ff7] == 0xff) { // FIRQ
45                         rom[0x4ff6] = 0x9f;
46                         rom[0x4ff7] = 0x74;
47                 }
48                 if(rom[0x4ff8] == 0xff && rom[0x4ff9] == 0xff) { // IRQ
49                         rom[0x4ff8] = 0x9f;
50                         rom[0x4ff9] = 0x77;
51                 }
52                 if(rom[0x4ffa] == 0xff && rom[0x4ffb] == 0xff) { // SWI
53                         rom[0x4ffa] = 0x9f;
54                         rom[0x4ffb] = 0x7a;
55                 }
56                 if(rom[0x4ffc] == 0xff && rom[0x4ffd] == 0xff) { // NMI
57                         rom[0x4ffc] = 0x9f;
58                         rom[0x4ffd] = 0x7d;
59                 }
60                 if(rom[0x4ffe] == 0xff && rom[0x4fff] == 0xff) { // RESET
61                         for(int i = 0; i < sizeof(rom) - 4; i++) {
62                                 static const uint8_t boot[4] = {0x86, 0x90, 0x1f, 0x8b};
63                                 if(memcmp(rom + i, boot, sizeof(boot)) == 0) {
64                                         i += 0xb000;
65                                         rom[0x4ffe] = (i >> 8) & 0xff;
66                                         rom[0x4fff] = (i >> 0) & 0xff;
67                                         break;
68                                 }
69                         }
70                 }
71         }
72         if(fio->Fopen(create_local_path(_T("ANK8.ROM")), FILEIO_READ_BINARY)) {
73                 fio->Fread(ank8, sizeof(ank8), 1);
74                 fio->Fclose();
75         }
76         if(fio->Fopen(create_local_path(_T("ANK16.ROM")), FILEIO_READ_BINARY)) {
77                 fio->Fread(ank16, sizeof(ank16), 1);
78                 fio->Fclose();
79         }
80         if(fio->Fopen(create_local_path(_T("KANJI16.ROM")), FILEIO_READ_BINARY)) {
81                 fio->Fread(kanji16, sizeof(kanji16), 1);
82                 fio->Fclose();
83         }
84         delete fio;
85         
86         set_memory_rw(0x9000, 0x9f7f, wram + 0x1000);
87         set_memory_rw(0x9f80, 0x9fff, sram);
88         set_memory_r (0xb000, 0xffff, rom);
89         
90         for(int i = 0; i < 8; i++) {
91                 palette_txt[i] = palette_cg[i] = RGB_COLOR(i & 2 ? 255 : 0, i & 4 ? 255 : 0, i & 1 ? 255 : 0);
92         }
93
94
95 }
96
97 void SUB::release()
98 {
99         MEMORY::release();
100 }
101
102 void SUB::reset()
103 {
104         MEMORY::reset();
105         
106         // reset crtc
107         blink = 0;
108         outctrl = 0xf;
109         
110         d_main->write_signal(SIG_MAIN_SUB_BUSY, 1, 1);
111         mix = 0x00;
112         
113         update = dispctrl = pagesel = 0;
114         ankcg = 0;
115         accaddr = dispaddr = 0;
116         
117         update_cvram_bank();
118         update_kvram_bank();
119         
120         memset(attention, 0, sizeof(attention));
121         mainack = 0x80;
122         
123         irq_cancel = irq_vsync = firq_key = firq_pen = false;
124         
125         kj_l = kj_h = kj_ofs = kj_row = 0;
126         
127         cmdreg = maskreg = compbit = bankdis = 0;
128         memset(compreg, 0xff, sizeof(compreg));
129 }
130
131 void SUB::write_data8(uint32_t addr, uint32_t data)
132 {
133         // sub cpu memory bus
134         write_memory(addr, data);
135 #ifdef _IO_DEBUG_LOG
136         if((addr >= 0x9f80 && addr < 0xa000) || (addr >= 0xff80 && addr < 0xffe0)) {
137                 this->out_debug_log(_T("SUB %06x\tOUT8\t%04x,%02x\n"), get_cpu_pc(1), addr, data);
138         }
139 #endif
140 }
141
142 uint32_t SUB::read_data8(uint32_t addr)
143 {
144         // sub cpu memory bus
145         uint32_t val = read_memory(addr);
146 #ifdef _IO_DEBUG_LOG
147         if((addr >= 0x9f80 && addr < 0xa000) || (addr >= 0xff80 && addr < 0xffe0)) {
148                 this->out_debug_log(_T("SUB %06x\tIN8\t%04x,%02x\n"), get_cpu_pc(1), addr, val);
149         }
150 #endif
151         return val;
152 }
153
154 void SUB::write_memory_mapped_io8(uint32_t addr, uint32_t data)
155 {
156         // main cpu direct access
157         addr &= 0xffff;
158         write_memory(addr, data);
159 #ifdef _IO_DEBUG_LOG
160         if((addr >= 0x9f80 && addr < 0xa000) || (addr >= 0xff80 && addr < 0xffe0)) {
161                 this->out_debug_log(_T("MAIN %06x\tOUT8\t%04x,%02x\n"), get_cpu_pc(0), addr, data);
162         }
163 #endif
164 }
165
166 uint32_t SUB::read_memory_mapped_io8(uint32_t addr)
167 {
168         // main cpu direct access
169         addr &= 0xffff;
170         uint32_t val = read_memory(addr);
171 #ifdef _IO_DEBUG_LOG
172         if((addr >= 0x9f80 && addr < 0xa000) || (addr >= 0xff80 && addr < 0xffe0)) {
173                 this->out_debug_log(_T("MAIN %06x\tIN8\t%04x,%02x\n"), get_cpu_pc(1), addr, val);
174         }
175 #endif
176         return val;
177 }
178
179 void SUB::write_memory(uint32_t addr, uint32_t data)
180 {
181         if(addr < 0x8000) {
182                 if(dispctrl & 0x40) {
183                         uint32_t bank = (pagesel >> 4) & 1;
184                         addr &= 0x7fff;
185                         addr |= bank << 15;
186                 } else {
187                         uint32_t bank = (pagesel >> 3) & 3;
188                         addr &= 0x3fff;
189                         addr |= bank << 14;
190                 }
191                 if(update & 1) gvram[addr | 0x00000] = data;
192                 if(update & 2) gvram[addr | 0x10000] = data;
193                 if(update & 4) gvram[addr | 0x20000] = data;
194         } else if(addr >= 0xff80 && addr < 0xffe0) {
195                 uint8_t change;
196                 
197                 switch(addr) {
198                 case 0xff80:
199                         d_main->write_signal(SIG_MAIN_SUB_BUSY, ~data, 1);
200                         mix = data;
201                         break;
202                 case 0xff81:
203                         update = data;
204                         break;
205                 case 0xff82:
206                         dispctrl = data;
207                         break;
208                 case 0xff83:
209                         change = pagesel ^ data;
210                         pagesel = data;
211                         if(change & 0x20) {
212                                 update_cvram_bank();
213                         }
214                         break;
215
216
217
218
219                 case 0xff87:
220                         d_main->write_signal(SIG_MAIN_FIRQ0, 1, 1);
221                         mainack &= ~0x80;
222                         break;
223
224                 case 0xff88:
225                         accaddr = (accaddr & 0x00ff) | (data << 8);
226                         break;
227                 case 0xff89:
228                         accaddr = (accaddr & 0xff00) | (data << 0);
229                         break;
230                 case 0xff8a:
231                         dispaddr = (dispaddr & 0x00ff) | (data << 8);
232                         break;
233                 case 0xff8b:
234                         dispaddr = (dispaddr & 0xff00) | (data << 0);
235                         break;
236
237                 case 0xff8e:
238                 case 0xff8f:
239                         d_crtc->write_io8(addr, data);
240                         break;
241
242                 case 0xff90:
243                 case 0xff91:
244                 case 0xff92:
245                         attention[addr & 3] = data;
246                         break;
247                 case 0xff94:
248                         kj_h = data & 0x7f;
249                         break;
250                 case 0xff95:
251                         kj_l = data & 0x7f;
252                         kj_row = 0;
253                         if(kj_h < 0x30) {
254                                 kj_ofs = (((kj_l - 0x00) & 0x1f) <<  5) | (((kj_l - 0x20) & 0x20) <<  9) | (((kj_l - 0x20) & 0x40) <<  7) | (((kj_h - 0x00) & 0x07) << 10);
255                         } else if(kj_h < 0x70) {
256                                 kj_ofs = (((kj_l - 0x00) & 0x1f) <<  5) + (((kj_l - 0x20) & 0x60) <<  9) + (((kj_h - 0x00) & 0x0f) << 10) + (((kj_h - 0x30) & 0x70) * 0xc00) + 0x08000;
257                         } else {
258                                 kj_ofs = (((kj_l - 0x00) & 0x1f) <<  5) | (((kj_l - 0x20) & 0x20) <<  9) | (((kj_l - 0x20) & 0x40) <<  7) | (((kj_h - 0x00) & 0x07) << 10) | 0x38000;
259                         }
260                         break;
261                 case 0xff96:
262                         kanji16[(kj_ofs | ((kj_row & 0xf) << 1)) & 0x3ffff] = data;
263                         break;
264                 case 0xff97:
265                         kanji16[(kj_ofs | ((kj_row++ & 0xf) << 1) | 1) & 0x3ffff] = data;
266                         break;
267
268                 case 0xff98:
269                         d_pcm->write_signal(SIG_PCM1BIT_ON, 0, 0);
270                         break;
271
272                 case 0xff99:
273                         change = ankcg ^ data;
274                         ankcg = data;
275                         if(change & 0x01) {
276                                 update_kvram_bank();
277                         }
278                         if(change & 0x80) {
279                                 update_kvram_bank();
280                         }
281                         break;
282
283                 case 0xffa0:
284                         cmdreg = data;
285                         break;
286                 case 0xffa1:
287                         imgcol = data;
288                         break;
289                 case 0xffa2:
290                         maskreg = data;
291                         break;
292                 case 0xffa3:
293                 case 0xffa4:
294                 case 0xffa5:
295                 case 0xffa6:
296                 case 0xffa7:
297                 case 0xffa8:
298                 case 0xffa9:
299                 case 0xffaa:
300                         compreg[addr & 7] = data;
301                         break;
302                 case 0xffab:
303                         bankdis = data;
304                         break;
305                 case 0xffac:
306                 case 0xffad:
307                 case 0xffae:
308                 case 0xffaf:
309                         tilereg[addr & 3] = data;
310                         break;
311                 case 0xffb0:
312                         lofs = (lofs & 0xff) | (data << 8);
313                         break;
314                 case 0xffb1:
315                         lofs = (lofs & 0xff00) | data;
316                         break;
317                 case 0xffb2:
318                         lsty = (lsty & 0xff) | (data << 8);
319                         break;
320                 case 0xffb3:
321                         lsty = (lsty & 0xff00) | data;
322                         break;
323                 case 0xffb4:
324                         lsx = (lsx & 0xff) | (data << 8);
325                         break;
326                 case 0xffb5:
327                         lsx = (lsx & 0xff00) | data;
328                         break;
329                 case 0xffb6:
330                         lsy = (lsy & 0xff) | (data << 8);
331                         break;
332                 case 0xffb7:
333                         lsy = (lsy & 0xff00) | data;
334                         break;
335                 case 0xffb8:
336                         lex = (lex & 0xff) | (data << 8);
337                         break;
338                 case 0xffb9:
339                         lex = (lex & 0xff00) | data;
340                         break;
341                 case 0xffba:
342                         ley = (ley & 0xff) | (data << 8);
343                         break;
344                 case 0xffbb:
345                         ley = (ley & 0xff00) | data;
346                         // start drawing line
347                         line();
348                         break;
349 #ifdef _IO_DEBUG_LOG
350                 default:
351                         this->out_debug_log(_T("UNKNOWN:\t"));
352                         break;
353 #endif
354                 }
355         } else {
356                 MEMORY::write_data8(addr, data);
357         }
358 }
359
360 uint32_t SUB::read_memory(uint32_t addr)
361 {
362         if(addr < 0x8000) {
363                 if(dispctrl & 0x40) {
364                         uint32_t bank = (pagesel >> 4) & 1;
365                         addr &= 0x7fff;
366                         addr |= bank << 15;
367                 } else {
368                         uint32_t bank = (pagesel >> 3) & 3;
369                         addr &= 0x3fff;
370                         addr |= bank << 14;
371                 }
372                 switch(update & 0xc0) {
373                 case 0x00: return gvram[addr | 0x00000];
374                 case 0x40: return gvram[addr | 0x10000];
375                 case 0x80: return gvram[addr | 0x20000];
376                 }
377                 return 0xff;
378         } else if(addr >= 0xff80 && addr < 0xffe0) {
379                 switch(addr) {
380                 case 0xff80:
381                         // bit5: Cursor LSB
382                         // bit4: Light Pen FIRQ 0:Disabled 1:Enabled
383                         // bit3: WIDTH 0:40 1:80
384                         // bit2: FLASH 0:OFF 1:ON
385                         // bit1: INSLED 0:OFF 1:ON
386                         // bit0: SUB BUSY 0:BUSY 1:READY
387                         return mix | 0xc0;
388                 case 0xff81:
389                         // bit7: Read Out Control RC2
390                         // bit6: Read Out Control RC1
391                         // bit2: RAM Select Bit RAM3
392                         // bit1: RAM Select Bit RAM2
393                         // bit0: RAM Select Bit RAM1
394                         return update | 0x38;
395                 case 0xff83:
396                         return pagesel | 0xc7;
397
398                 case 0xff84:
399                         {
400                                 uint8_t val = (firq_key ? 0x01 : 0) | (firq_pen ? 0x80 : 0);
401                                 firq_key = firq_pen = false;
402                                 update_firq();
403                                 return val;
404                         }
405
406                 case 0xff85:
407                         {
408                                 uint8_t val = (irq_cancel ? 0x01 : 0) | (irq_vsync ? 0x02 : 0) | 0x7e;
409                                 irq_cancel = irq_vsync = false;
410                                 update_irq();
411                                 return val;
412                         }
413
414
415
416                 case 0xff86:
417                         return (disp ? 0x80 : 0) | (vsync ? 0x04 : 0) | 0x70;
418
419                 case 0xff87:
420                         d_main->write_signal(SIG_MAIN_FIRQ0, 1, 1);
421                         mainack &= ~0x80;
422                         break;
423
424                 case 0xff8c:
425                 case 0xff8d:
426                         return d_keyboard->read_io8(addr);
427                 case 0xff8e:
428                 case 0xff8f:
429                         return d_crtc->read_io8(addr);
430                 case 0xff90:
431                 case 0xff91:
432                 case 0xff92:
433                         return attention[addr & 3];
434                 case 0xff93:
435                         return mainack;
436                 case 0xff94:
437                         return 0x80; // \91æ\93ñ\90\85\8f\80\82 \82è
438                 case 0xff96:
439                         return kanji16[(kj_ofs | ((kj_row & 0xf) << 1)) & 0x3ffff];
440                 case 0xff97:
441                         return kanji16[(kj_ofs | ((kj_row++ & 0xf) << 1) | 1) & 0x3ffff];
442                 case 0xff98:
443                         d_pcm->write_signal(SIG_PCM1BIT_ON, 1, 1);
444                         break;
445
446                 case 0xff99:
447                         return ankcg;
448                 case 0xffa0:
449                         return cmdreg;
450                 case 0xffa1:
451                         return imgcol | 0xf0;
452                 case 0xffa2:
453                         return maskreg;
454                 case 0xffa3:
455                         return compbit;
456                 case 0xffab:
457                         return bankdis & 0x0f;
458
459                 case 0xffb0:
460                         return (lofs >> 8) & 0xff;
461                 case 0xffb1:
462                         return (lofs >> 0) & 0xff;
463 #ifdef _IO_DEBUG_LOG
464                 default:
465                         this->out_debug_log(_T("UNKNOWN:\t"));
466                         break;
467 #endif
468                 }
469                 return 0xff;
470         } else {
471                 return MEMORY::read_data8(addr);
472         }
473 }
474
475 void SUB::write_io8(uint32_t addr, uint32_t data)
476 {
477         // main cpu i/o bus
478         switch(addr) {
479         case 0xfd98:
480         case 0xfd99:
481         case 0xfd9a:
482         case 0xfd9b:
483         case 0xfd9c:
484         case 0xfd9d:
485         case 0xfd9e:
486         case 0xfd9f:
487                 // digital palette
488                 if(data & 8) {
489                         palette_cg[addr & 7] = RGB_COLOR(data & 2 ? 255 : 0, data & 4 ? 255 : 0, data & 1 ? 255 : 0);
490                 } else {
491                         palette_cg[addr & 7] = RGB_COLOR(data & 2 ? 127 : 0, data & 4 ? 127 : 0, data & 1 ? 127 : 0);
492                 }
493                 dpal[addr & 7] = data;
494                 break;
495         case 0xfda0:
496                 outctrl = data;
497                 break;
498         // 0xfc80 - 0xfcff
499         default:
500                 sram[addr & 0x7f] = data;
501                 break;
502         }
503 }
504
505 uint32_t SUB::read_io8(uint32_t addr)
506 {
507         // main cpu i/o bus
508         switch(addr) {
509         case 0xfd20:
510         case 0xfd21:
511         case 0xfd22:
512                 return attention[addr & 3];
513
514         case 0xfd98:
515         case 0xfd99:
516         case 0xfd9a:
517         case 0xfd9b:
518         case 0xfd9c:
519         case 0xfd9d:
520         case 0xfd9e:
521         case 0xfd9f:
522                 // digital palette
523                 return dpal[addr & 7] | 0xf0;
524         // 0xfc80 - 0xfcff
525         default:
526                 return sram[addr & 0x7f];
527         }
528         return 0xff;
529 }
530
531 void SUB::write_signal(int id, uint32_t data, uint32_t mask)
532 {
533         if(id == SIG_SUB_DISP) {
534                 disp = ((data & mask) != 0);
535         } else if(id == SIG_SUB_VSYNC) {
536                 irq_vsync = vsync = ((data & mask) != 0);
537                 update_irq();
538         } else if(id == SIG_SUB_CANCEL) {
539                 irq_cancel = ((data & mask) != 0);
540                 update_irq();
541 this->out_debug_log("MAIN -> SUB: CANCEL = %d\n", irq_cancel);
542
543         } else if(id == SIG_SUB_KEY) {
544                 firq_key = ((data & mask) != 0);
545                 update_firq();
546         } else if(id == SIG_SUB_HALT) {
547 this->out_debug_log("MAIN -> SUB: HALT = %d\n", data & mask ?1 : 0);
548                 if(data & mask) {
549                         d_main->write_signal(SIG_MAIN_SUB_BUSY, 1, 1);
550                         mix &= ~0x01;
551                 }
552                 d_subcpu->write_signal(SIG_CPU_BUSREQ, data, mask);
553         } else if(id == SIG_SUB_MAINACK) {
554 this->out_debug_log("MAIN -> SUB: MAINACK = %d\n", data & mask ? 1 : 0);
555                 if(data & mask) {
556                         d_main->write_signal(SIG_MAIN_FIRQ0, 0, 0);
557                         mainack |= 0x80;
558                 }
559         }
560 }
561
562 void SUB::update_irq()
563 {
564         d_subcpu->write_signal(SIG_CPU_IRQ, irq_cancel || (irq_vsync && (ankcg & 0x80)) ? 1 : 0, 1);
565 }
566
567 void SUB::update_firq()
568 {
569         d_subcpu->write_signal(SIG_CPU_FIRQ, firq_key || (firq_pen &&  (mix & 0x10)) ? 1 : 0, 1);
570 }
571
572 void SUB::update_cvram_bank()
573 {
574         if(pagesel & 0x20) {
575                 set_memory_rw(0x8000, 0x8fff, wram);
576         } else {
577                 set_memory_rw(0x8000, 0x8fff, cvram);
578         }
579 }
580
581 void SUB::update_kvram_bank()
582 {
583         if(ankcg & 0x01) {
584                 set_memory_r(0xa000, 0xa7ff, ank8);
585                 set_memory_r(0xa800, 0xafff, ank8);
586         } else {
587                 set_memory_rw(0xa000, 0xafff, kvram);
588         }
589 }
590
591 void SUB::key_down(int code)
592 {
593         
594 }
595
596 void SUB::key_up(int code)
597 {
598         
599 }
600
601 void SUB::point(int x, int y, int col)
602 {
603         if(x < 640 && y < 400) {
604                 int ofs = ((lofs & 0x3fff) + (x >> 3) + y * 80) & 0x7fff;
605                 uint8_t bit = 0x80 >> (x & 7);
606                 for(int pl = 0; pl < 3; pl++) {
607                         uint8_t pbit = 1 << pl;
608                         if(!(bankdis & pbit)) {
609                                 if(col & pbit) {
610                                         gvram[0x8000 * pl + ofs] |= bit;
611                                 } else {
612                                         gvram[0x8000 * pl + ofs] &= ~bit;
613                                 }
614                         }
615                 }
616         }
617 }
618
619 void SUB::line()
620 {
621         int nx = lsx, ny = lsy;
622         int dx = abs(lex - lsx) * 2;
623         int dy = abs(ley - lsy) * 2;
624         int sx = (lex < lsx) ? -1 : 1;
625         int sy = (ley < lsy) ? -1 : 1;
626         int c = 0;
627         
628         point(lsx, lsy, (lsty & (0x8000 >> (c++ & 15))) ? imgcol : 0);
629         if(dx > dy) {
630                 int frac = dy - dx / 2;
631                 while(nx != lex) {
632                         if(frac >= 0) {
633                                 ny += sy;
634                                 frac -= dx;
635                         }
636                         nx += sx;
637                         frac += dy;
638                         point(nx, ny, (lsty & (0x8000 >> (c++ & 15))) ? imgcol : 0);
639                 }
640         } else {
641                 int frac = dx - dy / 2;
642                 while(ny != ley) {
643                         if(frac >= 0) {
644                                 nx += sx;
645                                 frac -= dy;
646                         }
647                         ny += sy;
648                         frac += dx;
649                         point(nx, ny, (lsty & (0x8000 >> (c++ & 15))) ? imgcol : 0);
650                 }
651         }
652 //      point(lex, ley, (lsty & (0x8000 >> (c++ & 15))) ? imgcol : 0);
653 }
654
655 void SUB::draw_screen()
656 {
657         // render screen
658         memset(screen_txt, 0, sizeof(screen_txt));
659         memset(screen_cg, 0, sizeof(screen_cg));
660         
661         if(outctrl & 1) {
662                 if(mix & 8) {
663                         draw_text80();
664                 } else {
665                         draw_text40();
666                 }
667         } else if(outctrl & 2) {
668                 // greem text
669         }
670         if(outctrl & 4) {
671                 draw_cg();
672         } else if(outctrl & 8) {
673                 // green graphics
674         }
675         
676         for(int y = 0; y < SCREEN_HEIGHT; y++) {
677                 scrntype_t* dest = emu->get_screen_buffer(y);
678                 uint8_t* txt = screen_txt[y];
679                 uint8_t* cg = screen_cg[y];
680                 
681                 for(int x = 0; x < SCREEN_WIDTH; x++) {
682                         dest[x] = txt[x] ? palette_txt[txt[x] & 15] : palette_cg[cg[x]];
683                 }
684         }
685         emu->screen_skip_line(false);
686 }
687
688 void SUB::draw_text40()
689 {
690         int src = ((chreg[12] << 9) | (chreg[13] << 1)) & 0xfff;
691         int caddr = ((chreg[8] & 0xc0) == 0xc0) ? -1 : (((chreg[14] << 9) | (chreg[15] << 1) | (mix & 0x20 ? 1 : 0)) & 0x7ff);
692         int ymax = (chreg[6] > 0) ? chreg[6] : 25;
693         int yofs = 400 / ymax;
694         
695         for(int y = 0; y < ymax; y++) {
696                 for(int x = 0; x < 40; x++) {
697                         bool cursor = ((src >> 1) == caddr);
698                         int cx = x;
699                         uint8_t code = cvram[src];
700                         uint8_t h = kvram[src] & 0x7f;
701                         src = (src + 1) & 0xfff;
702                         uint8_t attr = cvram[src];
703                         uint8_t l = kvram[src] & 0x7f;
704                         src = (src + 1) & 0xfff;
705                         uint8_t col = ((attr & 0x20) >> 2) | (attr & 7) | 16;
706                         bool blnk = (blink & 32) && (attr & 0x10);
707                         bool rev = ((attr & 8) != 0);
708                         uint8_t xor_mask = (rev != blnk) ? 0xff : 0;
709                         
710                         if(attr & 0x40) {
711                                 // kanji
712                                 int ofs;
713                                 if(h < 0x30) {
714                                         ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10);
715                                 } else if(h < 0x70) {
716                                         ofs = (((l - 0x00) & 0x1f) <<  5) + (((l - 0x20) & 0x60) <<  9) + (((h - 0x00) & 0x0f) << 10) + (((h - 0x30) & 0x70) * 0xc00) + 0x08000;
717                                 } else {
718                                         ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10) | 0x38000;
719                                 }
720                                 
721                                 for(int l = 0; l < 16 && l < yofs; l++) {
722                                         uint8_t pat0 = kanji16[ofs + (l << 1) + 0] ^ xor_mask;
723                                         uint8_t pat1 = kanji16[ofs + (l << 1) + 1] ^ xor_mask;
724                                         int yy = y * yofs + l;
725                                         if(yy >= 400) {
726                                                 break;
727                                         }
728                                         uint8_t* d = &screen_txt[yy][x << 4];
729                                         
730                                         d[ 0] = d[ 1] = (pat0 & 0x80) ? col : 0;
731                                         d[ 2] = d[ 3] = (pat0 & 0x40) ? col : 0;
732                                         d[ 4] = d[ 5] = (pat0 & 0x20) ? col : 0;
733                                         d[ 6] = d[ 7] = (pat0 & 0x10) ? col : 0;
734                                         d[ 8] = d[ 9] = (pat0 & 0x08) ? col : 0;
735                                         d[10] = d[11] = (pat0 & 0x04) ? col : 0;
736                                         d[12] = d[13] = (pat0 & 0x02) ? col : 0;
737                                         d[14] = d[15] = (pat0 & 0x01) ? col : 0;
738                                         d[16] = d[17] = (pat1 & 0x80) ? col : 0;
739                                         d[18] = d[19] = (pat1 & 0x40) ? col : 0;
740                                         d[20] = d[21] = (pat1 & 0x20) ? col : 0;
741                                         d[22] = d[23] = (pat1 & 0x10) ? col : 0;
742                                         d[24] = d[25] = (pat1 & 0x08) ? col : 0;
743                                         d[26] = d[27] = (pat1 & 0x04) ? col : 0;
744                                         d[28] = d[29] = (pat1 & 0x02) ? col : 0;
745                                         d[30] = d[31] = (pat1 & 0x01) ? col : 0;
746                                 }
747                                 src = (src + 2) & 0xfff;
748                                 x++;
749                         } else {
750                                 for(int l = 0; l < 16 && l < yofs; l++) {
751                                         uint8_t pat = ank16[(code << 4) + l] ^ xor_mask;
752                                         int yy = y * yofs + l;
753                                         if(yy >= 400) {
754                                                 break;
755                                         }
756                                         uint8_t* d = &screen_txt[yy][x << 4];
757                                         
758                                         d[ 0] = d[ 1] = (pat & 0x80) ? col : 0;
759                                         d[ 2] = d[ 3] = (pat & 0x40) ? col : 0;
760                                         d[ 4] = d[ 5] = (pat & 0x20) ? col : 0;
761                                         d[ 6] = d[ 7] = (pat & 0x10) ? col : 0;
762                                         d[ 8] = d[ 9] = (pat & 0x08) ? col : 0;
763                                         d[10] = d[11] = (pat & 0x04) ? col : 0;
764                                         d[12] = d[13] = (pat & 0x02) ? col : 0;
765                                         d[14] = d[15] = (pat & 0x01) ? col : 0;
766                                 }
767                         }
768                         if(cursor) {
769                                 int bp = chreg[10] & 0x60;
770                                 if(bp == 0 || (bp == 0x40 && (blink & 8)) || (bp == 0x60 && (blink & 0x10))) {
771                                         int st = chreg[10] & 15;
772                                         int ed = chreg[11] & 15;
773                                         for(int i = st; i < ed && i < yofs; i++) {
774                                                 memset(&screen_txt[y * yofs + i][cx << 3], 7, 8);
775                                         }
776                                 }
777                         }
778                 }
779         }
780 }
781
782 void SUB::draw_text80()
783 {
784         int src = ((chreg[12] << 9) | (chreg[13] << 1)) & 0xfff;
785         int caddr = ((chreg[8] & 0xc0) == 0xc0) ? -1 : (((chreg[14] << 9) | (chreg[15] << 1) | (mix & 0x20 ? 1 : 0)) & 0x7ff);
786         int ymax = (chreg[6] > 0) ? chreg[6] : 25;
787         int yofs = 400 / ymax;
788         
789         for(int y = 0; y < 25; y++) {
790                 for(int x = 0; x < 80; x++) {
791                         bool cursor = ((src >> 1) == caddr);
792                         int cx = x;
793                         uint8_t code = cvram[src];
794                         uint8_t h = kvram[src] & 0x7f;
795                         src = (src + 1) & 0xfff;
796                         uint8_t attr = cvram[src];
797                         uint8_t l = kvram[src] & 0x7f;
798                         src = (src + 1) & 0xfff;
799                         uint8_t col = ((attr & 0x20) >> 2) | (attr & 7) | 16;
800                         bool blnk = (blink & 32) && (attr & 0x10);
801                         bool rev = ((attr & 8) != 0);
802                         uint8_t xor_mask = (rev != blnk) ? 0xff : 0;
803                         
804                         if(attr & 0x40) {
805                                 // kanji
806                                 int ofs;
807                                 if(h < 0x30) {
808                                         ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10);
809                                 } else if(h < 0x70) {
810                                         ofs = (((l - 0x00) & 0x1f) <<  5) + (((l - 0x20) & 0x60) <<  9) + (((h - 0x00) & 0x0f) << 10) + (((h - 0x30) & 0x70) * 0xc00) + 0x08000;
811                                 } else {
812                                         ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10) | 0x38000;
813                                 }
814                                 
815                                 for(int l = 0; l < 16 && l < yofs; l++) {
816                                         uint8_t pat0 = kanji16[ofs + (l << 1) + 0] ^ xor_mask;
817                                         uint8_t pat1 = kanji16[ofs + (l << 1) + 1] ^ xor_mask;
818                                         int yy = y * yofs + l;
819                                         if(yy >= 400) {
820                                                 break;
821                                         }
822                                         uint8_t* d = &screen_txt[yy][x << 3];
823                                         
824                                         d[ 0] = (pat0 & 0x80) ? col : 0;
825                                         d[ 1] = (pat0 & 0x40) ? col : 0;
826                                         d[ 2] = (pat0 & 0x20) ? col : 0;
827                                         d[ 3] = (pat0 & 0x10) ? col : 0;
828                                         d[ 4] = (pat0 & 0x08) ? col : 0;
829                                         d[ 5] = (pat0 & 0x04) ? col : 0;
830                                         d[ 6] = (pat0 & 0x02) ? col : 0;
831                                         d[ 7] = (pat0 & 0x01) ? col : 0;
832                                         d[ 8] = (pat1 & 0x80) ? col : 0;
833                                         d[ 9] = (pat1 & 0x40) ? col : 0;
834                                         d[10] = (pat1 & 0x20) ? col : 0;
835                                         d[11] = (pat1 & 0x10) ? col : 0;
836                                         d[12] = (pat1 & 0x08) ? col : 0;
837                                         d[13] = (pat1 & 0x04) ? col : 0;
838                                         d[14] = (pat1 & 0x02) ? col : 0;
839                                         d[15] = (pat1 & 0x01) ? col : 0;
840                                 }
841                                 src = (src + 2) & 0xfff;
842                                 x++;
843                         } else {
844                                 for(int l = 0; l < 16 && l < yofs; l++) {
845                                         uint8_t pat = ank16[(code << 4) + l] ^ xor_mask;
846                                         int yy = y * yofs + l;
847                                         if(yy >= 400) {
848                                                 break;
849                                         }
850                                         uint8_t* d = &screen_txt[yy][x << 3];
851                                         
852                                         d[0] = (pat & 0x80) ? col : 0;
853                                         d[1] = (pat & 0x40) ? col : 0;
854                                         d[2] = (pat & 0x20) ? col : 0;
855                                         d[3] = (pat & 0x10) ? col : 0;
856                                         d[4] = (pat & 0x08) ? col : 0;
857                                         d[5] = (pat & 0x04) ? col : 0;
858                                         d[6] = (pat & 0x02) ? col : 0;
859                                         d[7] = (pat & 0x01) ? col : 0;
860                                 }
861                         }
862                         if(cursor) {
863                                 int bp = chreg[10] & 0x60;
864                                 if(bp == 0 || (bp == 0x40 && (blink & 8)) || (bp == 0x60 && (blink & 0x10))) {
865                                         int st = chreg[10] & 15;
866                                         int ed = chreg[11] & 15;
867                                         for(int i = st; i < ed && i < yofs; i++) {
868                                                 memset(&screen_txt[y * yofs + i][cx << 3], 7, 8);
869                                         }
870                                 }
871                         }
872                 }
873         }
874 }
875
876 void SUB::draw_cg()
877 {
878         if(dispctrl & 0x40) {
879                 // 400line
880                 int pofs = ((dispctrl >> 3) & 1) * 0x20000;
881                 uint8_t* p0 = (dispctrl & 0x01) ? &gvram[pofs | 0x00000] : dummy;
882                 uint8_t* p1 = (dispctrl & 0x02) ? &gvram[pofs | 0x08000] : dummy;
883                 uint8_t* p2 = (dispctrl & 0x04) ? &gvram[pofs | 0x10000] : dummy;
884                 int ptr = dispaddr & 0x7ffe;
885                 
886                 for(int y = 0; y < 400; y++) {
887                         for(int x = 0; x < 640; x += 8) {
888                                 uint8_t r = p0[ptr];
889                                 uint8_t g = p1[ptr];
890                                 uint8_t b = p2[ptr++];
891                                 ptr &= 0x7fff;
892                                 uint8_t* d = &screen_cg[y][x];
893                                 
894                                 d[0] = ((r & 0x80) >> 7) | ((g & 0x80) >> 6) | ((b & 0x80) >> 5);
895                                 d[1] = ((r & 0x40) >> 6) | ((g & 0x40) >> 5) | ((b & 0x40) >> 4);
896                                 d[2] = ((r & 0x20) >> 5) | ((g & 0x20) >> 4) | ((b & 0x20) >> 3);
897                                 d[3] = ((r & 0x10) >> 4) | ((g & 0x10) >> 3) | ((b & 0x10) >> 2);
898                                 d[4] = ((r & 0x08) >> 3) | ((g & 0x08) >> 2) | ((b & 0x08) >> 1);
899                                 d[5] = ((r & 0x04) >> 2) | ((g & 0x04) >> 1) | ((b & 0x04) >> 0);
900                                 d[6] = ((r & 0x02) >> 1) | ((g & 0x02) >> 0) | ((b & 0x02) << 1);
901                                 d[7] = ((r & 0x01) >> 0) | ((g & 0x01) << 1) | ((b & 0x01) << 2);
902                         }
903                 }
904         } else {
905                 // 200line
906                 int pofs = ((dispctrl >> 3) & 3) * 0x10000;
907                 uint8_t* p0 = (dispctrl & 0x01) ? &gvram[pofs | 0x0000] : dummy;
908                 uint8_t* p1 = (dispctrl & 0x02) ? &gvram[pofs | 0x4000] : dummy;
909                 uint8_t* p2 = (dispctrl & 0x04) ? &gvram[pofs | 0x8000] : dummy;
910                 int ptr = dispaddr & 0x3ffe;
911                 
912                 for(int y = 0; y < 400; y += 2) {
913                         for(int x = 0; x < 640; x += 8) {
914                                 uint8_t r = p0[ptr];
915                                 uint8_t g = p1[ptr];
916                                 uint8_t b = p2[ptr++];
917                                 ptr &= 0x3fff;
918                                 uint8_t* d = &screen_cg[y][x];
919                                 
920                                 d[0] = ((r & 0x80) >> 7) | ((g & 0x80) >> 6) | ((b & 0x80) >> 5);
921                                 d[1] = ((r & 0x40) >> 6) | ((g & 0x40) >> 5) | ((b & 0x40) >> 4);
922                                 d[2] = ((r & 0x20) >> 5) | ((g & 0x20) >> 4) | ((b & 0x20) >> 3);
923                                 d[3] = ((r & 0x10) >> 4) | ((g & 0x10) >> 3) | ((b & 0x10) >> 2);
924                                 d[4] = ((r & 0x08) >> 3) | ((g & 0x08) >> 2) | ((b & 0x08) >> 1);
925                                 d[5] = ((r & 0x04) >> 2) | ((g & 0x04) >> 1) | ((b & 0x04) >> 0);
926                                 d[6] = ((r & 0x02) >> 1) | ((g & 0x02) >> 0) | ((b & 0x02) << 1);
927                                 d[7] = ((r & 0x01) >> 0) | ((g & 0x01) << 1) | ((b & 0x01) << 2);
928                         }
929                         memcpy(screen_cg[y + 1], screen_cg[y], 640);
930                 }
931         }
932 }
933
934 #define STATE_VERSION   1
935
936 void SUB::save_state(FILEIO* state_fio)
937 {
938         state_fio->FputUint32(STATE_VERSION);
939         state_fio->FputInt32(this_device_id);
940         
941         MEMORY::save_state(state_fio);
942 }
943
944 bool SUB::load_state(FILEIO* state_fio)
945 {
946         if(state_fio->FgetUint32() != STATE_VERSION) {
947                 return false;
948         }
949         if(state_fio->FgetInt32() != this_device_id) {
950                 return false;
951         }
952         if(!MEMORY::load_state(state_fio)) {
953                 return false;
954         }
955         return true;
956 }
957