2 FUJITSU FMR-30 Emulator 'eFMR-30'
4 Author : Takeda.Toshiya
14 static const uint8 bios1[] = {
17 0xB8,0x00,0x7F, // mov ax,7F00
18 0x8E,0xD0, // mov ss,ax
19 0xBC,0x64,0x0F, // mov sp,0F64
21 0xB4,0x80, // mov ah,80
22 0x9A,0x14,0x00,0xFB,0xFF, // call far FFFB:0014
24 0xB4,0x81, // mov ah,81
25 0x9A,0x14,0x00,0xFB,0xFF, // call far FFFB:0014
26 0x73,0x0B, // jnb $+11
29 0xB4,0x82, // mov ah,82
30 0x9A,0x14,0x00,0xFB,0xFF, // call far FFFB:0014
33 0x9A,0x04,0x00,0x00,0xB0, // call far B000:0004
37 static const uint8 bios2[] = {
38 0xEA,0x00,0x00,0x00,0xFC, // jmp FC00:0000
43 #define SET_BANK(s, e, w, r) { \
44 int sb = (s) >> 12, eb = (e) >> 12; \
45 for(int i = sb; i <= eb; i++) { \
49 wbank[i] = (w) + 0x1000 * (i - sb); \
54 rbank[i] = (r) + 0x1000 * (i - sb); \
59 void MEMORY::initialize()
62 memset(ram, 0, sizeof(ram));
63 memset(vram, 0, sizeof(vram));
64 memset(cvram, 0, sizeof(cvram));
65 memset(kvram, 0, sizeof(kvram));
66 memset(ipl, 0xff, sizeof(ipl));
67 memset(kanji16, 0xff, sizeof(kanji16));
68 memset(rdmy, 0xff, sizeof(rdmy));
71 FILEIO* fio = new FILEIO();
72 if(fio->Fopen(emu->bios_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
73 fio->Fread(ipl, sizeof(ipl), 1);
77 memcpy(ipl + 0xc000, bios1, sizeof(bios1));
78 memcpy(ipl + 0xfff0, bios2, sizeof(bios2));
81 if(fio->Fopen(emu->bios_path(_T("ANK8.ROM")), FILEIO_READ_BINARY)) {
82 fio->Fread(ipl, 0x800, 1);
85 if(fio->Fopen(emu->bios_path(_T("ANK16.ROM")), FILEIO_READ_BINARY)) {
86 fio->Fread(ipl + 0x800, 0x1000, 1);
90 if(fio->Fopen(emu->bios_path(_T("KANJI16.ROM")), FILEIO_READ_BINARY)) {
91 fio->Fread(kanji16, sizeof(kanji16), 1);
97 SET_BANK(0x000000, 0xffffff, wdmy, rdmy);
98 SET_BANK(0x000000, sizeof(ram) - 1, ram, ram);
99 SET_BANK(0xff0000, 0xffffff, wdmy, ipl);
102 register_frame_event(this);
109 memset(lcdreg, 0, sizeof(lcdreg));
111 kj_l = kj_h = kj_ofs = kj_row = 0;
120 void MEMORY::write_data8(uint32 addr, uint32 data)
123 wbank[addr >> 12][addr & 0xfff] = data;
126 uint32 MEMORY::read_data8(uint32 addr)
129 return rbank[addr >> 12][addr & 0xfff];
132 void MEMORY::write_io8(uint32 addr, uint32 data)
134 switch(addr & 0xffff) {
140 // d_cpu->write_signal(SIG_I86_A20, data, 0x10);
149 d_cpu->write_signal(SIG_I86_A20, data, 0x80);
156 d_dma->write_signal(SIG_I8237_BANK0 + (addr & 3), data, 0x0f);
163 lcdreg[lcdadr & 31] = data;
166 dcr1 = (dcr1 & 0xff00) | data;
169 dcr1 = (dcr1 & 0xff) | (data << 8);
170 // bit11-10: vram bank
174 dcr1 = (dcr1 & 0xff00) | data;
177 dcr1 = (dcr1 & 0xff) | (data << 8);
187 kj_ofs = (((kj_l - 0x00) & 0x1f) << 5) | (((kj_l - 0x20) & 0x20) << 9) | (((kj_l - 0x20) & 0x40) << 7) | (((kj_h - 0x00) & 0x07) << 10);
188 } else if(kj_h < 0x70) {
189 kj_ofs = (((kj_l - 0x00) & 0x1f) << 5) + (((kj_l - 0x20) & 0x60) << 9) + (((kj_h - 0x00) & 0x0f) << 10) + (((kj_h - 0x30) & 0x70) * 0xc00) + 0x08000;
191 kj_ofs = (((kj_l - 0x00) & 0x1f) << 5) | (((kj_l - 0x20) & 0x20) << 9) | (((kj_l - 0x20) & 0x40) << 7) | (((kj_h - 0x00) & 0x07) << 10) | 0x38000;
195 kanji16[(kj_ofs | ((kj_row & 0x0f) << 1)) & 0x3ffff] = data;
198 kanji16[(kj_ofs | ((kj_row++ & 0x0f) << 1) | 1) & 0x3ffff] = data;
203 uint32 MEMORY::read_io8(uint32 addr)
207 switch(addr & 0xffff) {
218 return lcdreg[lcdadr & 31];
222 return (dcr1 >> 8) & 0xff;
226 return (dcr2 >> 8) & 0xff;
233 return kanji16[(kj_ofs | ((kj_row & 0x0f) << 1)) & 0x3ffff];
235 return kanji16[(kj_ofs | ((kj_row++ & 0x0f) << 1) | 1) & 0x3ffff];
240 void MEMORY::event_frame()
245 void MEMORY::update_bank()
248 // $c0000-$cffff: vram
249 SET_BANK(0xc0000, 0xcffff, wdmy, rdmy);
250 int bank = 0x8000 * ((dcr1 >> 10) & 3);
251 SET_BANK(0xc0000, 0xc7fff, vram + bank, vram + bank);
252 SET_BANK(0xc8000, 0xc8fff, cvram, cvram);
253 SET_BANK(0xca000, 0xcafff, kvram, kvram);
255 SET_BANK(0xc0000, 0xcffff, ram + 0xc0000, ram + 0xc0000);
259 SET_BANK(0xf0000, 0xfffff, wdmy, ipl);
261 SET_BANK(0xf0000, 0xfffff, ram + 0xf0000, ram + 0xf0000);
265 void MEMORY::draw_screen()
268 memset(screen_txt, 0, sizeof(screen_txt));
269 memset(screen_cg, 0, sizeof(screen_cg));
281 scrntype cd = RGB_COLOR(48, 56, 16);
282 scrntype cb = RGB_COLOR(160, 168, 160);
283 for(int y = 0; y < 400; y++) {
284 scrntype* dest = emu->screen_buffer(y);
285 uint8* txt = screen_txt[y];
286 uint8* cg = screen_cg[y];
288 for(int x = 0; x < 640; x++) {
289 dest[x] = (txt[x] || cg[x]) ? cd : cb;
294 void MEMORY::draw_text40()
297 uint8 *ank16 = ipl + 0x800;
299 int src = 0;//((lcdreg[12] << 9) | (lcdreg[13] << 1)) & 0xfff;
300 int caddr = (lcdreg[10] & 0x20) ? -1 : (((lcdreg[14] << 9) | (lcdreg[15] << 1)) & 0xfff);
301 int yofs = lcdreg[9] + 1;
302 int ymax = 400 / yofs;
303 int freq = (dcr1 >> 4) & 3;
304 bool blink = !((freq == 3) || (blinkcnt & (32 >> freq)));
306 for(int y = 0; y < ymax; y++) {
307 for(int x = 0; x < 40; x++) {
308 bool cursor = (src == caddr);
310 uint8 code = cvram[src];
311 uint8 h = kvram[src] & 0x7f;
312 src = (src + 1) & 0xfff;
313 uint8 attr = cvram[src];
314 uint8 l = kvram[src] & 0x7f;
315 src = (src + 1) & 0xfff;
316 uint8 col = attr & 0x27;
317 bool blnk = blink && (attr & 0x10);
318 bool rev = ((attr & 8) != 0);
324 ofs = (((l - 0x00) & 0x1f) << 5) | (((l - 0x20) & 0x20) << 9) | (((l - 0x20) & 0x40) << 7) | (((h - 0x00) & 0x07) << 10);
325 } else if(h < 0x70) {
326 ofs = (((l - 0x00) & 0x1f) << 5) + (((l - 0x20) & 0x60) << 9) + (((h - 0x00) & 0x0f) << 10) + (((h - 0x30) & 0x70) * 0xc00) + 0x08000;
328 ofs = (((l - 0x00) & 0x1f) << 5) | (((l - 0x20) & 0x20) << 9) | (((l - 0x20) & 0x40) << 7) | (((h - 0x00) & 0x07) << 10) | 0x38000;
331 for(int l = 0; l < 16 && l < yofs; l++) {
332 uint8 pat0 = kanji16[ofs + (l << 1) + 0];
333 uint8 pat1 = kanji16[ofs + (l << 1) + 1];
334 pat0 = blnk ? 0 : rev ? ~pat0 : pat0;
335 pat1 = blnk ? 0 : rev ? ~pat1 : pat1;
336 int yy = y * yofs + l;
340 uint8* d = &screen_txt[yy][x << 4];
342 d[ 0] = d[ 1] = (pat0 & 0x80) ? col : 0;
343 d[ 2] = d[ 3] = (pat0 & 0x40) ? col : 0;
344 d[ 4] = d[ 5] = (pat0 & 0x20) ? col : 0;
345 d[ 6] = d[ 7] = (pat0 & 0x10) ? col : 0;
346 d[ 8] = d[ 9] = (pat0 & 0x08) ? col : 0;
347 d[10] = d[11] = (pat0 & 0x04) ? col : 0;
348 d[12] = d[13] = (pat0 & 0x02) ? col : 0;
349 d[14] = d[15] = (pat0 & 0x01) ? col : 0;
350 d[16] = d[17] = (pat1 & 0x80) ? col : 0;
351 d[18] = d[19] = (pat1 & 0x40) ? col : 0;
352 d[20] = d[21] = (pat1 & 0x20) ? col : 0;
353 d[22] = d[23] = (pat1 & 0x10) ? col : 0;
354 d[24] = d[25] = (pat1 & 0x08) ? col : 0;
355 d[26] = d[27] = (pat1 & 0x04) ? col : 0;
356 d[28] = d[29] = (pat1 & 0x02) ? col : 0;
357 d[30] = d[31] = (pat1 & 0x01) ? col : 0;
359 src = (src + 2) & 0xfff;
362 for(int l = 0; l < 16 && l < yofs; l++) {
363 uint8 pat = ank16[(code << 4) + l];
364 pat = blnk ? 0 : rev ? ~pat : pat;
365 int yy = y * yofs + l;
369 uint8* d = &screen_txt[yy][x << 4];
371 d[ 0] = d[ 1] = (pat & 0x80) ? col : 0;
372 d[ 2] = d[ 3] = (pat & 0x40) ? col : 0;
373 d[ 4] = d[ 5] = (pat & 0x20) ? col : 0;
374 d[ 6] = d[ 7] = (pat & 0x10) ? col : 0;
375 d[ 8] = d[ 9] = (pat & 0x08) ? col : 0;
376 d[10] = d[11] = (pat & 0x04) ? col : 0;
377 d[12] = d[13] = (pat & 0x02) ? col : 0;
378 d[14] = d[15] = (pat & 0x01) ? col : 0;
381 if(cursor && !blink) {
382 int st = lcdreg[10] & 0x1f;
383 int ed = lcdreg[11] & 0x1f;
384 for(int i = st; i <= ed && i < yofs; i++) {
385 memset(&screen_txt[y * yofs + i][cx << 4], 7, 8);
392 void MEMORY::draw_text80()
395 uint8 *ank16 = ipl + 0x800;
397 int src = 0;//((lcdreg[12] << 9) | (lcdreg[13] << 1)) & 0xfff;
398 int caddr = (lcdreg[10] & 0x20) ? -1 : (((lcdreg[14] << 9) | (lcdreg[15] << 1)) & 0xfff);
399 int yofs = lcdreg[9] + 1;
400 int ymax = 400 / yofs;
401 int freq = (dcr1 >> 4) & 3;
402 bool blink = !((freq == 3) || (blinkcnt & (32 >> freq)));
404 for(int y = 0; y < ymax; y++) {
405 for(int x = 0; x < 80; x++) {
406 bool cursor = (src == caddr);
408 uint8 code = cvram[src];
409 uint8 h = kvram[src] & 0x7f;
410 src = (src + 1) & 0xfff;
411 uint8 attr = cvram[src];
412 uint8 l = kvram[src] & 0x7f;
413 src = (src + 1) & 0xfff;
414 uint8 col = attr & 0x27;
415 bool blnk = blink && (attr & 0x10);
416 bool rev = ((attr & 8) != 0);
422 ofs = (((l - 0x00) & 0x1f) << 5) | (((l - 0x20) & 0x20) << 9) | (((l - 0x20) & 0x40) << 7) | (((h - 0x00) & 0x07) << 10);
423 } else if(h < 0x70) {
424 ofs = (((l - 0x00) & 0x1f) << 5) + (((l - 0x20) & 0x60) << 9) + (((h - 0x00) & 0x0f) << 10) + (((h - 0x30) & 0x70) * 0xc00) + 0x08000;
426 ofs = (((l - 0x00) & 0x1f) << 5) | (((l - 0x20) & 0x20) << 9) | (((l - 0x20) & 0x40) << 7) | (((h - 0x00) & 0x07) << 10) | 0x38000;
429 for(int l = 0; l < 16 && l < yofs; l++) {
430 uint8 pat0 = kanji16[ofs + (l << 1) + 0];
431 uint8 pat1 = kanji16[ofs + (l << 1) + 1];
432 pat0 = blnk ? 0 : rev ? ~pat0 : pat0;
433 pat1 = blnk ? 0 : rev ? ~pat1 : pat1;
434 int yy = y * yofs + l;
438 uint8* d = &screen_txt[yy][x << 3];
440 d[ 0] = (pat0 & 0x80) ? col : 0;
441 d[ 1] = (pat0 & 0x40) ? col : 0;
442 d[ 2] = (pat0 & 0x20) ? col : 0;
443 d[ 3] = (pat0 & 0x10) ? col : 0;
444 d[ 4] = (pat0 & 0x08) ? col : 0;
445 d[ 5] = (pat0 & 0x04) ? col : 0;
446 d[ 6] = (pat0 & 0x02) ? col : 0;
447 d[ 7] = (pat0 & 0x01) ? col : 0;
448 d[ 8] = (pat1 & 0x80) ? col : 0;
449 d[ 9] = (pat1 & 0x40) ? col : 0;
450 d[10] = (pat1 & 0x20) ? col : 0;
451 d[11] = (pat1 & 0x10) ? col : 0;
452 d[12] = (pat1 & 0x08) ? col : 0;
453 d[13] = (pat1 & 0x04) ? col : 0;
454 d[14] = (pat1 & 0x02) ? col : 0;
455 d[15] = (pat1 & 0x01) ? col : 0;
457 src = (src + 2) & 0xfff;
460 for(int l = 0; l < 16 && l < yofs; l++) {
461 uint8 pat = ank16[(code << 4) + l];
462 pat = blnk ? 0 : rev ? ~pat : pat;
463 int yy = y * yofs + l;
467 uint8* d = &screen_txt[yy][x << 3];
469 d[0] = (pat & 0x80) ? col : 0;
470 d[1] = (pat & 0x40) ? col : 0;
471 d[2] = (pat & 0x20) ? col : 0;
472 d[3] = (pat & 0x10) ? col : 0;
473 d[4] = (pat & 0x08) ? col : 0;
474 d[5] = (pat & 0x04) ? col : 0;
475 d[6] = (pat & 0x02) ? col : 0;
476 d[7] = (pat & 0x01) ? col : 0;
479 if(cursor && !blink) {
480 int st = lcdreg[10] & 0x1f;
481 int ed = lcdreg[11] & 0x1f;
482 for(int i = st; i <= ed && i < yofs; i++) {
483 memset(&screen_txt[y * yofs + i][cx << 3], 7, 8);
490 void MEMORY::draw_cg()
492 uint8* plane = vram + ((dcr1 >> 8) & 3) * 0x8000;
495 for(int y = 0; y < 400; y++) {
496 for(int x = 0; x < 640; x += 8) {
497 uint8 pat = plane[ptr++];
498 uint8* d = &screen_cg[y][x];
512 #define STATE_VERSION 1
514 void MEMORY::save_state(FILEIO* state_fio)
516 state_fio->FputUint32(STATE_VERSION);
517 state_fio->FputInt32(this_device_id);
519 state_fio->Fwrite(ram, sizeof(ram), 1);
520 state_fio->Fwrite(vram, sizeof(vram), 1);
521 state_fio->Fwrite(cvram, sizeof(cvram), 1);
522 state_fio->Fwrite(kvram, sizeof(kvram), 1);
523 state_fio->FputUint8(mcr1);
524 state_fio->FputUint8(mcr2);
525 state_fio->FputUint8(a20);
526 state_fio->FputUint8(lcdadr);
527 state_fio->Fwrite(lcdreg, sizeof(lcdreg), 1);
528 state_fio->FputUint16(dcr1);
529 state_fio->FputUint16(dcr2);
530 state_fio->FputInt32(kj_h);
531 state_fio->FputInt32(kj_l);
532 state_fio->FputInt32(kj_ofs);
533 state_fio->FputInt32(kj_row);
534 state_fio->FputInt32(blinkcnt);
537 bool MEMORY::load_state(FILEIO* state_fio)
539 if(state_fio->FgetUint32() != STATE_VERSION) {
542 if(state_fio->FgetInt32() != this_device_id) {
545 state_fio->Fread(ram, sizeof(ram), 1);
546 state_fio->Fread(vram, sizeof(vram), 1);
547 state_fio->Fread(cvram, sizeof(cvram), 1);
548 state_fio->Fread(kvram, sizeof(kvram), 1);
549 mcr1 = state_fio->FgetUint8();
550 mcr2 = state_fio->FgetUint8();
551 a20 = state_fio->FgetUint8();
552 lcdadr = state_fio->FgetUint8();
553 state_fio->Fread(lcdreg, sizeof(lcdreg), 1);
554 dcr1 = state_fio->FgetUint16();
555 dcr2 = state_fio->FgetUint16();
556 kj_h = state_fio->FgetInt32();
557 kj_l = state_fio->FgetInt32();
558 kj_ofs = state_fio->FgetInt32();
559 kj_row = state_fio->FgetInt32();
560 blinkcnt = state_fio->FgetInt32();