2 FUJITSU FMR-30 Emulator 'eFMR-30'
4 Author : Takeda.Toshiya
11 #include "../../emu.h"
16 static const uint8_t bios1[] = {
19 0xB8,0x00,0x7F, // mov ax,7F00
20 0x8E,0xD0, // mov ss,ax
21 0xBC,0x64,0x0F, // mov sp,0F64
23 0xB4,0x80, // mov ah,80
24 0x9A,0x14,0x00,0xFB,0xFF, // call far FFFB:0014
26 0xB4,0x81, // mov ah,81
27 0x9A,0x14,0x00,0xFB,0xFF, // call far FFFB:0014
28 0x73,0x0B, // jnb $+11
31 0xB4,0x82, // mov ah,82
32 0x9A,0x14,0x00,0xFB,0xFF, // call far FFFB:0014
35 0x9A,0x04,0x00,0x00,0xB0, // call far B000:0004
39 static const uint8_t bios2[] = {
40 0xEA,0x00,0x00,0x00,0xFC, // jmp FC00:0000
45 #define SET_BANK(s, e, w, r) { \
46 int sb = (s) >> 12, eb = (e) >> 12; \
47 for(int i = sb; i <= eb; i++) { \
51 wbank[i] = (w) + 0x1000 * (i - sb); \
56 rbank[i] = (r) + 0x1000 * (i - sb); \
61 void MEMORY::initialize()
64 memset(ram, 0, sizeof(ram));
65 memset(vram, 0, sizeof(vram));
66 memset(cvram, 0, sizeof(cvram));
67 memset(kvram, 0, sizeof(kvram));
68 memset(ipl, 0xff, sizeof(ipl));
69 memset(kanji16, 0xff, sizeof(kanji16));
70 memset(rdmy, 0xff, sizeof(rdmy));
73 FILEIO* fio = new FILEIO();
74 if(fio->Fopen(create_local_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
75 fio->Fread(ipl, sizeof(ipl), 1);
79 memcpy(ipl + 0xc000, bios1, sizeof(bios1));
80 memcpy(ipl + 0xfff0, bios2, sizeof(bios2));
83 if(fio->Fopen(create_local_path(_T("ANK8.ROM")), FILEIO_READ_BINARY)) {
84 fio->Fread(ipl, 0x800, 1);
87 if(fio->Fopen(create_local_path(_T("ANK16.ROM")), FILEIO_READ_BINARY)) {
88 fio->Fread(ipl + 0x800, 0x1000, 1);
92 if(fio->Fopen(create_local_path(_T("KANJI16.ROM")), FILEIO_READ_BINARY)) {
93 fio->Fread(kanji16, sizeof(kanji16), 1);
99 SET_BANK(0x000000, 0xffffff, wdmy, rdmy);
100 SET_BANK(0x000000, sizeof(ram) - 1, ram, ram);
101 SET_BANK(0x0f0000, 0x0fffff, wdmy, ipl);
102 SET_BANK(0xff0000, 0xffffff, wdmy, ipl);
105 register_frame_event(this);
112 memset(lcdreg, 0, sizeof(lcdreg));
114 kj_l = kj_h = kj_ofs = kj_row = 0;
123 void MEMORY::write_data8(uint32_t addr, uint32_t data)
126 wbank[addr >> 12][addr & 0xfff] = data;
129 uint32_t MEMORY::read_data8(uint32_t addr)
132 return rbank[addr >> 12][addr & 0xfff];
135 void MEMORY::write_io8(uint32_t addr, uint32_t data)
137 switch(addr & 0xffff) {
142 // d_cpu->write_signal(SIG_I286_A20, data, 0x10);
154 d_cpu->write_signal(SIG_I286_A20, data, 0x80);
163 d_dma->write_signal(SIG_I8237_BANK0 + (addr & 3), data, 0x0f);
170 lcdreg[lcdadr & 31] = data;
173 dcr1 = (dcr1 & 0xff00) | data;
176 dcr1 = (dcr1 & 0xff) | (data << 8);
177 // bit11-10: vram bank
181 dcr1 = (dcr1 & 0xff00) | data;
184 dcr1 = (dcr1 & 0xff) | (data << 8);
194 kj_ofs = (((kj_l - 0x00) & 0x1f) << 5) | (((kj_l - 0x20) & 0x20) << 9) | (((kj_l - 0x20) & 0x40) << 7) | (((kj_h - 0x00) & 0x07) << 10);
195 } else if(kj_h < 0x70) {
196 kj_ofs = (((kj_l - 0x00) & 0x1f) << 5) + (((kj_l - 0x20) & 0x60) << 9) + (((kj_h - 0x00) & 0x0f) << 10) + (((kj_h - 0x30) & 0x70) * 0xc00) + 0x08000;
198 kj_ofs = (((kj_l - 0x00) & 0x1f) << 5) | (((kj_l - 0x20) & 0x20) << 9) | (((kj_l - 0x20) & 0x40) << 7) | (((kj_h - 0x00) & 0x07) << 10) | 0x38000;
202 kanji16[(kj_ofs | ((kj_row & 0x0f) << 1)) & 0x3ffff] = data;
205 kanji16[(kj_ofs | ((kj_row++ & 0x0f) << 1) | 1) & 0x3ffff] = data;
210 uint32_t MEMORY::read_io8(uint32_t addr)
214 switch(addr & 0xffff) {
225 return lcdreg[lcdadr & 31];
229 return (dcr1 >> 8) & 0xff;
233 return (dcr2 >> 8) & 0xff;
240 return kanji16[(kj_ofs | ((kj_row & 0x0f) << 1)) & 0x3ffff];
242 return kanji16[(kj_ofs | ((kj_row++ & 0x0f) << 1) | 1) & 0x3ffff];
247 void MEMORY::event_frame()
252 void MEMORY::update_bank()
255 // $c0000-$cffff: vram
256 SET_BANK(0xc0000, 0xcffff, wdmy, rdmy);
257 int bank = 0x8000 * ((dcr1 >> 10) & 3);
258 SET_BANK(0xc0000, 0xc7fff, vram + bank, vram + bank);
259 SET_BANK(0xc8000, 0xc8fff, cvram, cvram);
260 SET_BANK(0xca000, 0xcafff, kvram, kvram);
262 SET_BANK(0xc0000, 0xcffff, ram + 0xc0000, ram + 0xc0000);
266 SET_BANK(0xf0000, 0xfffff, wdmy, ipl);
268 SET_BANK(0xf0000, 0xfffff, ram + 0xf0000, ram + 0xf0000);
272 void MEMORY::draw_screen()
275 memset(screen_txt, 0, sizeof(screen_txt));
276 memset(screen_cg, 0, sizeof(screen_cg));
288 scrntype_t cd = RGB_COLOR(48, 56, 16);
289 scrntype_t cb = RGB_COLOR(160, 168, 160);
290 for(int y = 0; y < 400; y++) {
291 scrntype_t* dest = emu->get_screen_buffer(y);
292 uint8_t* txt = screen_txt[y];
293 uint8_t* cg = screen_cg[y];
295 for(int x = 0; x < 640; x++) {
296 dest[x] = (txt[x] || cg[x]) ? cd : cb;
301 void MEMORY::draw_text40()
304 uint8_t *ank16 = ipl + 0x800;
306 int src = 0;//((lcdreg[12] << 9) | (lcdreg[13] << 1)) & 0xfff;
307 int caddr = (lcdreg[10] & 0x20) ? -1 : (((lcdreg[14] << 9) | (lcdreg[15] << 1)) & 0xfff);
308 int yofs = lcdreg[9] + 1;
309 int ymax = 400 / yofs;
310 int freq = (dcr1 >> 4) & 3;
311 bool blink = !((freq == 3) || (blinkcnt & (32 >> freq)));
313 for(int y = 0; y < ymax; y++) {
314 for(int x = 0; x < 40; x++) {
315 bool cursor = (src == caddr);
317 uint8_t code = cvram[src];
318 uint8_t h = kvram[src] & 0x7f;
319 src = (src + 1) & 0xfff;
320 uint8_t attr = cvram[src];
321 uint8_t l = kvram[src] & 0x7f;
322 src = (src + 1) & 0xfff;
323 uint8_t col = attr & 0x27;
324 bool blnk = blink && (attr & 0x10);
325 bool rev = ((attr & 8) != 0);
331 ofs = (((l - 0x00) & 0x1f) << 5) | (((l - 0x20) & 0x20) << 9) | (((l - 0x20) & 0x40) << 7) | (((h - 0x00) & 0x07) << 10);
332 } else if(h < 0x70) {
333 ofs = (((l - 0x00) & 0x1f) << 5) + (((l - 0x20) & 0x60) << 9) + (((h - 0x00) & 0x0f) << 10) + (((h - 0x30) & 0x70) * 0xc00) + 0x08000;
335 ofs = (((l - 0x00) & 0x1f) << 5) | (((l - 0x20) & 0x20) << 9) | (((l - 0x20) & 0x40) << 7) | (((h - 0x00) & 0x07) << 10) | 0x38000;
338 for(int l = 0; l < 16 && l < yofs; l++) {
339 uint8_t pat0 = kanji16[ofs + (l << 1) + 0];
340 uint8_t pat1 = kanji16[ofs + (l << 1) + 1];
341 pat0 = blnk ? 0 : rev ? ~pat0 : pat0;
342 pat1 = blnk ? 0 : rev ? ~pat1 : pat1;
343 int yy = y * yofs + l;
347 uint8_t* d = &screen_txt[yy][x << 4];
349 d[ 0] = d[ 1] = (pat0 & 0x80) ? col : 0;
350 d[ 2] = d[ 3] = (pat0 & 0x40) ? col : 0;
351 d[ 4] = d[ 5] = (pat0 & 0x20) ? col : 0;
352 d[ 6] = d[ 7] = (pat0 & 0x10) ? col : 0;
353 d[ 8] = d[ 9] = (pat0 & 0x08) ? col : 0;
354 d[10] = d[11] = (pat0 & 0x04) ? col : 0;
355 d[12] = d[13] = (pat0 & 0x02) ? col : 0;
356 d[14] = d[15] = (pat0 & 0x01) ? col : 0;
357 d[16] = d[17] = (pat1 & 0x80) ? col : 0;
358 d[18] = d[19] = (pat1 & 0x40) ? col : 0;
359 d[20] = d[21] = (pat1 & 0x20) ? col : 0;
360 d[22] = d[23] = (pat1 & 0x10) ? col : 0;
361 d[24] = d[25] = (pat1 & 0x08) ? col : 0;
362 d[26] = d[27] = (pat1 & 0x04) ? col : 0;
363 d[28] = d[29] = (pat1 & 0x02) ? col : 0;
364 d[30] = d[31] = (pat1 & 0x01) ? col : 0;
366 src = (src + 2) & 0xfff;
369 for(int l = 0; l < 16 && l < yofs; l++) {
370 uint8_t pat = ank16[(code << 4) + l];
371 pat = blnk ? 0 : rev ? ~pat : pat;
372 int yy = y * yofs + l;
376 uint8_t* d = &screen_txt[yy][x << 4];
378 d[ 0] = d[ 1] = (pat & 0x80) ? col : 0;
379 d[ 2] = d[ 3] = (pat & 0x40) ? col : 0;
380 d[ 4] = d[ 5] = (pat & 0x20) ? col : 0;
381 d[ 6] = d[ 7] = (pat & 0x10) ? col : 0;
382 d[ 8] = d[ 9] = (pat & 0x08) ? col : 0;
383 d[10] = d[11] = (pat & 0x04) ? col : 0;
384 d[12] = d[13] = (pat & 0x02) ? col : 0;
385 d[14] = d[15] = (pat & 0x01) ? col : 0;
388 if(cursor && !blink) {
389 int st = lcdreg[10] & 0x1f;
390 int ed = lcdreg[11] & 0x1f;
391 for(int i = st; i <= ed && i < yofs; i++) {
392 memset(&screen_txt[y * yofs + i][cx << 4], 7, 8);
399 void MEMORY::draw_text80()
402 uint8_t *ank16 = ipl + 0x800;
404 int src = 0;//((lcdreg[12] << 9) | (lcdreg[13] << 1)) & 0xfff;
405 int caddr = (lcdreg[10] & 0x20) ? -1 : (((lcdreg[14] << 9) | (lcdreg[15] << 1)) & 0xfff);
406 int yofs = lcdreg[9] + 1;
407 int ymax = 400 / yofs;
408 int freq = (dcr1 >> 4) & 3;
409 bool blink = !((freq == 3) || (blinkcnt & (32 >> freq)));
411 for(int y = 0; y < ymax; y++) {
412 for(int x = 0; x < 80; x++) {
413 bool cursor = (src == caddr);
415 uint8_t code = cvram[src];
416 uint8_t h = kvram[src] & 0x7f;
417 src = (src + 1) & 0xfff;
418 uint8_t attr = cvram[src];
419 uint8_t l = kvram[src] & 0x7f;
420 src = (src + 1) & 0xfff;
421 uint8_t col = attr & 0x27;
422 bool blnk = blink && (attr & 0x10);
423 bool rev = ((attr & 8) != 0);
429 ofs = (((l - 0x00) & 0x1f) << 5) | (((l - 0x20) & 0x20) << 9) | (((l - 0x20) & 0x40) << 7) | (((h - 0x00) & 0x07) << 10);
430 } else if(h < 0x70) {
431 ofs = (((l - 0x00) & 0x1f) << 5) + (((l - 0x20) & 0x60) << 9) + (((h - 0x00) & 0x0f) << 10) + (((h - 0x30) & 0x70) * 0xc00) + 0x08000;
433 ofs = (((l - 0x00) & 0x1f) << 5) | (((l - 0x20) & 0x20) << 9) | (((l - 0x20) & 0x40) << 7) | (((h - 0x00) & 0x07) << 10) | 0x38000;
436 for(int l = 0; l < 16 && l < yofs; l++) {
437 uint8_t pat0 = kanji16[ofs + (l << 1) + 0];
438 uint8_t pat1 = kanji16[ofs + (l << 1) + 1];
439 pat0 = blnk ? 0 : rev ? ~pat0 : pat0;
440 pat1 = blnk ? 0 : rev ? ~pat1 : pat1;
441 int yy = y * yofs + l;
445 uint8_t* d = &screen_txt[yy][x << 3];
447 d[ 0] = (pat0 & 0x80) ? col : 0;
448 d[ 1] = (pat0 & 0x40) ? col : 0;
449 d[ 2] = (pat0 & 0x20) ? col : 0;
450 d[ 3] = (pat0 & 0x10) ? col : 0;
451 d[ 4] = (pat0 & 0x08) ? col : 0;
452 d[ 5] = (pat0 & 0x04) ? col : 0;
453 d[ 6] = (pat0 & 0x02) ? col : 0;
454 d[ 7] = (pat0 & 0x01) ? col : 0;
455 d[ 8] = (pat1 & 0x80) ? col : 0;
456 d[ 9] = (pat1 & 0x40) ? col : 0;
457 d[10] = (pat1 & 0x20) ? col : 0;
458 d[11] = (pat1 & 0x10) ? col : 0;
459 d[12] = (pat1 & 0x08) ? col : 0;
460 d[13] = (pat1 & 0x04) ? col : 0;
461 d[14] = (pat1 & 0x02) ? col : 0;
462 d[15] = (pat1 & 0x01) ? col : 0;
464 src = (src + 2) & 0xfff;
467 for(int l = 0; l < 16 && l < yofs; l++) {
468 uint8_t pat = ank16[(code << 4) + l];
469 pat = blnk ? 0 : rev ? ~pat : pat;
470 int yy = y * yofs + l;
474 uint8_t* d = &screen_txt[yy][x << 3];
476 d[0] = (pat & 0x80) ? col : 0;
477 d[1] = (pat & 0x40) ? col : 0;
478 d[2] = (pat & 0x20) ? col : 0;
479 d[3] = (pat & 0x10) ? col : 0;
480 d[4] = (pat & 0x08) ? col : 0;
481 d[5] = (pat & 0x04) ? col : 0;
482 d[6] = (pat & 0x02) ? col : 0;
483 d[7] = (pat & 0x01) ? col : 0;
486 if(cursor && !blink) {
487 int st = lcdreg[10] & 0x1f;
488 int ed = lcdreg[11] & 0x1f;
489 for(int i = st; i <= ed && i < yofs; i++) {
490 memset(&screen_txt[y * yofs + i][cx << 3], 7, 8);
497 void MEMORY::draw_cg()
499 uint8_t* plane = vram + ((dcr1 >> 8) & 3) * 0x8000;
502 for(int y = 0; y < 400; y++) {
503 for(int x = 0; x < 640; x += 8) {
504 uint8_t pat = plane[ptr++];
505 uint8_t* d = &screen_cg[y][x];
519 #define STATE_VERSION 2
521 void MEMORY::save_state(FILEIO* state_fio)
523 state_fio->FputUint32(STATE_VERSION);
524 state_fio->FputInt32(this_device_id);
526 state_fio->Fwrite(ram, sizeof(ram), 1);
527 state_fio->Fwrite(vram, sizeof(vram), 1);
528 state_fio->Fwrite(cvram, sizeof(cvram), 1);
529 state_fio->Fwrite(kvram, sizeof(kvram), 1);
530 state_fio->FputUint8(mcr1);
531 state_fio->FputUint8(mcr2);
532 state_fio->FputUint8(a20);
533 state_fio->FputUint8(lcdadr);
534 state_fio->Fwrite(lcdreg, sizeof(lcdreg), 1);
535 state_fio->FputUint16(dcr1);
536 state_fio->FputUint16(dcr2);
537 state_fio->FputInt32(kj_h);
538 state_fio->FputInt32(kj_l);
539 state_fio->FputInt32(kj_ofs);
540 state_fio->FputInt32(kj_row);
541 state_fio->FputInt32(blinkcnt);
544 bool MEMORY::load_state(FILEIO* state_fio)
546 if(state_fio->FgetUint32() != STATE_VERSION) {
549 if(state_fio->FgetInt32() != this_device_id) {
552 state_fio->Fread(ram, sizeof(ram), 1);
553 state_fio->Fread(vram, sizeof(vram), 1);
554 state_fio->Fread(cvram, sizeof(cvram), 1);
555 state_fio->Fread(kvram, sizeof(kvram), 1);
556 mcr1 = state_fio->FgetUint8();
557 mcr2 = state_fio->FgetUint8();
558 a20 = state_fio->FgetUint8();
559 lcdadr = state_fio->FgetUint8();
560 state_fio->Fread(lcdreg, sizeof(lcdreg), 1);
561 dcr1 = state_fio->FgetUint16();
562 dcr2 = state_fio->FgetUint16();
563 kj_h = state_fio->FgetInt32();
564 kj_l = state_fio->FgetInt32();
565 kj_ofs = state_fio->FgetInt32();
566 kj_row = state_fio->FgetInt32();
567 blinkcnt = state_fio->FgetInt32();