X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=source%2Fsrc%2Fvm%2Fpc8801%2Fpc88.cpp;h=e78c144a43cbe7240bd62990e435425b8c16ea76;hb=8e87b770d1495e38439682db0df7083b1cbb8a42;hp=da0a2900262e7d9754e5ac893c48e14fe0adb994;hpb=cb772dac13d12126c3b0cf77c2a47fc53f5b705e;p=csp-qt%2Fcommon_source_project-fm7.git diff --git a/source/src/vm/pc8801/pc88.cpp b/source/src/vm/pc8801/pc88.cpp index da0a29002..e78c144a4 100644 --- a/source/src/vm/pc8801/pc88.cpp +++ b/source/src/vm/pc8801/pc88.cpp @@ -17,6 +17,11 @@ #include "../ym2203.h" #include "../z80.h" +#ifdef SUPPORT_PC88_CDROM +#include "../scsi_cdrom.h" +#include "../scsi_host.h" +#endif + #define DEVICE_JOYSTICK 0 #define DEVICE_MOUSE 1 #define DEVICE_JOYMOUSE 2 // not supported yet @@ -26,12 +31,19 @@ #define EVENT_CMT_SEND 2 #define EVENT_CMT_DCD 3 #define EVENT_BEEP 4 +#ifdef SUPPORT_PC88_CDROM +#define EVENT_FADE_IN 5 +#define EVENT_FADE_OUT 6 +#endif #define IRQ_USART 0 #define IRQ_VRTC 1 #define IRQ_TIMER 2 #define IRQ_SOUND 4 +namespace PC88DEV +{ + #define Port30_40 !(port[0x30] & 0x01) #define Port30_COLOR !(port[0x30] & 0x02) #define Port30_MTON (port[0x30] & 0x08) @@ -51,12 +63,15 @@ #define Port31_V1_320x200 (port[0x31] & 0x10) // PC-8001 (V1) #define Port31_V1_MONO (port[0x31] & 0x04) // PC-8001 (V1) -#define Port31_COLOR (port[0x31] & 0x10) // PC-8001 #define Port31_320x200 (port[0x31] & 0x04) // PC-8001 #define Port32_EROMSL (port[0x32] & 0x03) #define Port32_TMODE (port[0x32] & 0x10) +#if !defined(_PC8001SR) #define Port32_PMODE (port[0x32] & 0x20) +#else +#define Port32_PMODE false +#endif #define Port32_GVAM (port[0x32] & 0x40) #define Port32_SINTM (port[0x32] & 0x80) @@ -89,6 +104,10 @@ #define Port71_EROM port[0x71] +#ifdef SUPPORT_PC88_CDROM +#define Port99_CDREN (port[0x99] & 0x10) +#endif + // XM8 version 1.20 #define PortA8_OPNCH port[0xa8] #define PortAA_S2INTM (port[0xaa] & 0x80) @@ -108,6 +127,12 @@ #define PortF0_DICROMSL (port[0xf0] & 0x1f) #define PortF1_DICROM !(port[0xf1] & 0x01) +#if defined(SUPPORT_PC88_VAB) +// X88000 +#define PortB4_VAB_DISP ((port[0xb4] & 0x41) == 0x41) +#define PortE3_VAB_SEL (((port[0xe3] >> 2) & 3) == PC88_VAB_PAGE) +#endif + #define SET_BANK(s, e, w, r) { \ int sb = (s) >> 12, eb = (e) >> 12; \ for(int i = sb; i <= eb; i++) { \ @@ -155,29 +180,31 @@ static const int key_table[15][8] = { { 0x58, 0x59, 0x5a, 0xdb, 0xdc, 0xdd, 0xde, 0xbd }, { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 }, { 0x38, 0x39, 0xba, 0xbb, 0xbc, 0xbe, 0xbf, 0xe2 }, - { 0x24, 0x26, 0x27, 0x2e, 0x12, 0x15, 0x10, 0x11 }, +// { 0x24, 0x26, 0x27, 0x2e, 0x12, 0x15, 0x10, 0x11 }, + { 0x24, 0x26, 0x27, 0x08, 0x12, 0x15, 0x10, 0x11 }, { 0x13, 0x70, 0x71, 0x72, 0x73, 0x74, 0x20, 0x1b }, { 0x09, 0x28, 0x25, 0x23, 0x7b, 0x6d, 0x6f, 0x14 }, { 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x75, 0x76, 0x77, 0x78, 0x79, 0x08, 0x2d, 0x2e }, - { 0x1c, 0x1d, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00 }, + { 0x1c, 0x1d, 0x7a, 0x19, 0x00, 0x00, 0x00, 0x00 }, { 0x0d, 0x00, 0xa0, 0xa1, 0x00, 0x00, 0x00, 0x00 } }; -static const int key_conv_table[9][3] = { +static const int key_conv_table[][3] = { {0x2d, 0x2e, 1}, // INS -> SHIFT + DEL {0x75, 0x70, 1}, // F6 -> SHIFT + F1 {0x76, 0x71, 1}, // F7 -> SHIFT + F2 {0x77, 0x72, 1}, // F8 -> SHIFT + F3 {0x78, 0x73, 1}, // F9 -> SHIFT + F4 {0x79, 0x74, 1}, // F10 -> SHIFT + F5 - {0x08, 0x2e, 0}, // BS -> DEL +// {0x08, 0x2e, 0}, // BS -> DEL + {0x2e, 0x08, 0}, // DEL -> BS {0x1c, 0x20, 0}, // •ÏŠ·-> SPACE {0x1d, 0x20, 0}, // Œˆ’è-> SPACE }; -static const int16_t intr_mask2_table[8] = { - ~7, ~3, ~5, ~1, ~6, ~2, ~4, ~0 +static const uint8_t intr_mask2_table[8] = { + (uint8_t)~7, (uint8_t)~3, (uint8_t)~5, (uint8_t)~1, (uint8_t)~6, (uint8_t)~2, (uint8_t)~4, (uint8_t)~0 }; void PC88::initialize() @@ -203,6 +230,10 @@ void PC88::initialize() #ifdef SUPPORT_PC88_DICTIONARY memset(dicrom, 0xff, sizeof(dicrom)); #endif +#ifdef SUPPORT_PC88_CDROM + memset(cdbios, 0xff, sizeof(cdbios)); + cdbios_loaded = false; +#endif // load rom images FILEIO* fio = new FILEIO(); @@ -264,6 +295,15 @@ void PC88::initialize() fio->Fclose(); } #endif +#ifdef SUPPORT_PC88_CDROM + if(config.boot_mode == MODE_PC88_V2) { + if(fio->Fopen(create_local_path(_T("CDBIOS.ROM")), FILEIO_READ_BINARY)) { + fio->Fread(cdbios, 0x10000, 1); + fio->Fclose(); + cdbios_loaded = true; + } + } +#endif delete fio; // memory pattern @@ -304,13 +344,19 @@ void PC88::initialize() dest[6] = dest[7] = ((i & 8) ? 0xf0 : 0) | ((i & 0x80) ? 0x0f : 0); } - // initialize text/graph palette - for(int i = 0; i < 9; i++) { - palette_text_pc[i] = RGBA_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0, 255); // A is a flag for crt filter - } - for(int i = 0; i < 8; i++) { - palette_graph_pc[i] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0); +#ifdef SUPPORT_PC88_VAB + // X88000 + for(uint32_t g = 0; g < 64; g++) { + uint32_t gg = (255 * g) / 63; + for(uint32_t r = 0; r < 32; r++) { + uint32_t rr = (255 * r) / 31; + for(uint32_t b = 0; b < 32; b++) { + uint32_t bb = (255 * b) / 31; + palette_vab_pc[b | (r << 5) | (g << 10)] = RGB_COLOR(rr, gg, bb); + } + } } +#endif #ifdef SUPPORT_PC88_HIGH_CLOCK cpu_clock_low = (config.cpu_type == 1); // 4MHz @@ -333,6 +379,14 @@ void PC88::initialize() register_vline_event(this); register_event(this, EVENT_TIMER, 1000000.0 / 600.0, true, NULL); register_event(this, EVENT_BEEP, 1000000.0 / 4800.0, true, NULL); + +#if !defined(_PC8001SR) + // hack to update config.scan_line at first + hireso = !(config.monitor_type == 0); +#endif +#ifdef SUPPORT_PC88_CDROM + cdda_register_id = -1; +#endif } void PC88::release() @@ -346,7 +400,12 @@ void PC88::reset() #if defined(_PC8001SR) hireso = false; #else - hireso = (config.monitor_type == 0); + bool value = (config.monitor_type == 0); + if(hireso != value) { + // update config.scan_line when config.monitor_type is changed + //hireso = config.scan_line = value; + hireso = value; // Revert 20181217 K.O + } #endif // memory @@ -358,7 +417,11 @@ void PC88::reset() } // port[0x70] = 0x80; // XM8 version 1.10 port[0x71] = port[0xf1] = 0xff; - +#if defined(SUPPORT_PC88_CDROM) + if (cdbios_loaded) { + port[0x99] = 0x10; + } +#endif memset(alu_reg, 0, sizeof(alu_reg)); gvram_plane = gvram_sel = 0; @@ -371,8 +434,9 @@ void PC88::reset() } SET_BANK(0x8000, 0xffff, ram + 0x8000, ram + 0x8000); #else - SET_BANK(0x0000, 0x7fff, ram, n88rom); +// SET_BANK(0x0000, 0x7fff, ram, n88rom); SET_BANK(0x8000, 0xefff, ram + 0x8000, ram + 0x8000); + update_low_memmap(); update_tvram_memmap(); // XM8 version 1.10 #endif @@ -395,7 +459,8 @@ void PC88::reset() crtc.reset(hireso); update_timing(); - for(int i = 0; i < 9; i++) { + memset(palette, 0, sizeof(palette)); + for(int i = 1; i < 8; i++) { palette[i].b = (i & 1) ? 7 : 0; palette[i].r = (i & 2) ? 7 : 0; palette[i].g = (i & 4) ? 7 : 0; @@ -404,8 +469,14 @@ void PC88::reset() // dma memset(&dmac, 0, sizeof(dmac)); - dmac.mem = dmac.ch[2].io = this; - dmac.ch[0].io = dmac.ch[1].io = dmac.ch[3].io = vm->dummy; + dmac.ch[0].io = dmac.ch[3].io = vm->dummy; +#ifdef SUPPORT_PC88_CDROM + if(cdbios_loaded) { + dmac.ch[1].io = d_scsi_host; + } else +#endif + dmac.ch[1].io = vm->dummy;; + dmac.ch[2].io = dmac.mem = this; dmac.ch[0].addr.b.l = 0x56; // XM8 version 1.10 dmac.ch[0].addr.b.h = 0x56; dmac.ch[1].addr.b.l = 0x7a; @@ -447,6 +518,14 @@ void PC88::reset() write_io8(2, 0); write_io8(3, 0); #endif +#ifdef SUPPORT_PC88_CDROM + if(cdda_register_id != -1) { + cancel_event(this, cdda_register_id); + cdda_register_id = -1; + } + cdda_volume = 100.0; + d_scsi_cdrom->set_volume((int)cdda_volume); +#endif #ifdef NIPPY_PATCH // dirty patch for NIPPY nippy_patch = false; @@ -594,7 +673,7 @@ void PC88::write_io8(uint32_t addr, uint32_t data) { addr &= 0xff; #ifdef _IO_DEBUG_LOG - this->out_debug_log(_T("%6x\tOUT8\t%02x,%02x\n"), d_cpu->get_pc(), addr, data); + this->out_debug_log(_T("%06x\tOUT8\t%02x,%02x\n"), d_cpu->get_pc(), addr, data); #endif #ifdef NIPPY_PATCH // dirty patch for NIPPY @@ -743,6 +822,7 @@ void PC88::write_io8(uint32_t addr, uint32_t data) } if(mod & 0x08) { update_gvram_wait(); + update_palette = true; } if(mod & 0x11) { update_timing(); @@ -755,7 +835,7 @@ void PC88::write_io8(uint32_t addr, uint32_t data) break; case 0x32: if(mod & 0x03) { - if(Port71_EROM == 0xfe) { + if(!(Port71_EROM & 1)) { update_low_memmap(); } } @@ -849,7 +929,7 @@ void PC88::write_io8(uint32_t addr, uint32_t data) case 0x5b: #if !defined(_PC8001SR) if(Port32_PMODE) { - int n = (data & 0x80) ? 8 : (addr - 0x54); + int n = (data & 0x80) ? 9 : (addr - 0x54); if(data & 0x40) { palette[n].g = data & 7; } else { @@ -922,13 +1002,99 @@ void PC88::write_io8(uint32_t addr, uint32_t data) break; #else case 0x71: - if(mod) { + if(mod & 0x01) { update_low_memmap(); } break; case 0x78: Port70_TEXTWND++; break; +#ifdef SUPPORT_PC88_HMB20 + case 0x88: + case 0x89: + d_opm->write_io8(addr, data); + break; +#endif +#ifdef SUPPORT_PC88_CDROM + // M88 cdif + case 0x90: + if(cdbios_loaded && (mod & 0x01)) { + if(data & 0x01) { + if(port[0x9f] & 0x01) { + d_scsi_host->write_signal(SIG_SCSI_SEL, 0, 1); + d_scsi_host->write_signal(SIG_SCSI_SEL, 1, 1); + d_scsi_host->write_signal(SIG_SCSI_SEL, 0, 1); + } + } else { + d_scsi_host->write_signal(SIG_SCSI_SEL, 0, 1); + } +// d_scsi_host->write_signal(SIG_SCSI_SEL, data, 1); + } + break; + case 0x91: + if(cdbios_loaded) { + d_scsi_host->write_dma_io8(0, data); + } + break; + case 0x94: + if(cdbios_loaded) { + d_scsi_host->write_signal(SIG_SCSI_RST, data, 0x80); + } + break; + case 0x98: + if(cdbios_loaded) { + switch(data & 7) { + case 0: + case 1: + if(cdda_register_id != -1) { + cancel_event(this, cdda_register_id); + } + d_scsi_cdrom->set_volume((int)(cdda_volume = 100.0)); + break; + case 2: + case 3: + if(cdda_register_id != -1) { + cancel_event(this, cdda_register_id); + } + d_scsi_cdrom->set_volume((int)(cdda_volume = 0.0)); + break; + case 4: + if(cdda_register_id != -1) { + cancel_event(this, cdda_register_id); + } + register_event(this, EVENT_FADE_IN, 100, true, &cdda_register_id); // 100ms + d_scsi_cdrom->set_volume((int)(cdda_volume = 0.0)); + break; + case 5: + if(cdda_register_id != -1) { + cancel_event(this, cdda_register_id); + } + register_event(this, EVENT_FADE_IN, 1500, true, &cdda_register_id); // 1500ms + d_scsi_cdrom->set_volume((int)(cdda_volume = 0.0)); + break; + case 6: + if(cdda_register_id != -1) { + cancel_event(this, cdda_register_id); + } + register_event(this, EVENT_FADE_OUT, 100, true, &cdda_register_id); // 100ms + d_scsi_cdrom->set_volume((int)(cdda_volume = 100.0)); + break; + case 7: + if(cdda_register_id != -1) { + cancel_event(this, cdda_register_id); + } + register_event(this, EVENT_FADE_OUT, 5000, true, &cdda_register_id); // 5000ms + d_scsi_cdrom->set_volume((int)(cdda_volume = 100.0)); + break; + } + } + break; + case 0x99: + if(cdbios_loaded && (mod & 0x10)) { + update_low_memmap(); + } + break; +#endif #ifdef SUPPORT_PC88_SB2 case 0xa8: case 0xa9: @@ -958,8 +1124,14 @@ void PC88::write_io8(uint32_t addr, uint32_t data) } break; case 0xe3: +#ifdef PC88_IODATA_EXRAM if(mod) { - update_low_memmap(); +#else + if(mod & 0x0f) { +#endif + if(PortE2_RDEN || PortE2_WREN) { + update_low_memmap(); + } } break; #endif @@ -969,10 +1141,10 @@ void PC88::write_io8(uint32_t addr, uint32_t data) break; case 0xe6: // for Romancia (XM8 version 1.00) - if((uint8_t)intr_mask2_table[data & 7] != intr_mask2) { - intr_req &= ((uint8_t)intr_mask2_table[data & 7] & intr_mask2); + if(intr_mask2_table[data & 7] != intr_mask2) { + intr_req &= (intr_mask2_table[data & 7] & intr_mask2); } - intr_mask2 = (uint8_t)intr_mask2_table[data & 7]; + intr_mask2 = intr_mask2_table[data & 7]; intr_req &= intr_mask2; update_intr(); break; @@ -1144,6 +1316,62 @@ uint32_t PC88::read_io8_debug(uint32_t addr) #endif case 0x71: return port[0x71]; +#ifdef SUPPORT_PC88_HMB20 +// case 0x88: + case 0x89: + return d_opm->read_io8(addr); +#endif +#ifdef SUPPORT_PC88_CDROM + // M88 cdif + case 0x90: + if(cdbios_loaded) { + val = d_scsi_host->read_signal(SIG_SCSI_BSY) ? 0x80 : 0; + val |= d_scsi_host->read_signal(SIG_SCSI_REQ) ? 0x40 : 0; + val |= d_scsi_host->read_signal(SIG_SCSI_MSG) ? 0x20 : 0; + val |= d_scsi_host->read_signal(SIG_SCSI_CD ) ? 0x10 : 0; + val |= d_scsi_host->read_signal(SIG_SCSI_IO ) ? 0x08 : 0; + // do not show BSY,MSG,CxD,IxD when SEL=1 (M’·‚Ì–ì–] •«•—‰_˜^) + if(port[0x90] & 0x01) { + val &= ~(0x80 | 0x20 | 0x10 | 0x08); + val |= (port[0x9f] & 0x01); // correct ??? + } + #ifdef _SCSI_DEBUG_LOG + this->out_debug_log(_T("[SCSI_PC88] Status = %02X\n"), val); + #endif + return val; + } + break; + case 0x91: + if(cdbios_loaded) { + return d_scsi_host->read_dma_io8(0); + } + break; + case 0x92: + case 0x93: + case 0x96: + if(cdbios_loaded) { + return 0x00; + } + break; + case 0x99: + if(cdbios_loaded) { +// return 0xcd; // PC-8801MC + return 0x00; + } + break; + case 0x98: + if(cdbios_loaded) { + port[0x98] ^= 0x80; // clock ??? + return port[0x98]; + } + break; + case 0x9b: + case 0x9d: + if(cdbios_loaded) { + return 60; + } + break; +#endif #ifdef SUPPORT_PC88_SB2 case 0xa8: if(d_sb2 != NULL) { @@ -1195,6 +1423,15 @@ uint32_t PC88::read_io8_debug(uint32_t addr) break; #endif #endif +#if defined(SUPPORT_PC88_VAB) + // X88000 + case 0xb4: + case 0xb5: + if(PortE3_VAB_SEL) { + return port[addr]; + } + break; +#endif case 0xe2: return (~port[0xe2]) | 0xee; case 0xe3: @@ -1221,6 +1458,7 @@ uint32_t PC88::read_io8_debug(uint32_t addr) uint32_t PC88::read_dma_data8(uint32_t addr) { + // from ram #if defined(_PC8001SR) return ram[addr & 0xffff]; #else @@ -1232,6 +1470,12 @@ uint32_t PC88::read_dma_data8(uint32_t addr) #endif } +void PC88::write_dma_data8(uint32_t addr, uint32_t data) +{ + // to ram + ram[addr & 0xffff] = data; +} + void PC88::write_dma_io8(uint32_t addr, uint32_t data) { // to crtc @@ -1506,18 +1750,24 @@ void PC88::update_low_memmap() } else if(Port31_MMODE) { // 64K RAM SET_BANK_R(0x0000, 0x7fff, ram); +#ifdef SUPPORT_PC88_CDROM + } else if(cdbios_loaded && Port99_CDREN) { + if(Port31_RMODE) { + SET_BANK_R(0x0000, 0x7fff, cdbios + 0x8000); + } else { + SET_BANK_R(0x0000, 0x7fff, cdbios + 0x0000); + } +#endif } else if(Port31_RMODE) { // N-BASIC SET_BANK_R(0x0000, 0x7fff, n80rom); } else { // N-88BASIC SET_BANK_R(0x0000, 0x5fff, n88rom); - if(Port71_EROM == 0xff) { + if(Port71_EROM & 1) { SET_BANK_R(0x6000, 0x7fff, n88rom + 0x6000); - } else if(Port71_EROM == 0xfe) { - SET_BANK_R(0x6000, 0x7fff, n88exrom + 0x2000 * Port32_EROMSL); } else { - SET_BANK_R(0x6000, 0x7fff, rdmy); + SET_BANK_R(0x6000, 0x7fff, n88exrom + 0x2000 * Port32_EROMSL); } } @@ -1569,6 +1819,17 @@ void PC88::write_signal(int id, uint32_t data, uint32_t mask) request_intr(IRQ_SOUND, true); } #endif +#ifdef SUPPORT_PC88_CDROM + } else if(id == SIG_PC88_SCSI_DRQ) { + if((data & mask) && cdbios_loaded) { + if(!dmac.ch[1].running) { + dmac.start(1); + } + if(dmac.ch[1].running) { + dmac.run(1, 1); + } + } +#endif } else if(id == SIG_PC88_USART_OUT) { // recv from sio if(Port30_CMT) { @@ -1622,6 +1883,24 @@ void PC88::event_callback(int event_id, int err) beep_signal = !beep_signal; d_pcm->write_signal(SIG_PCM1BIT_SIGNAL, ((beep_on && beep_signal) || sing_signal) ? 1 : 0, 1); break; +#ifdef SUPPORT_PC88_CDROM + case EVENT_FADE_IN: + if((cdda_volume += 0.1) >= 100.0) { + cancel_event(this, cdda_register_id); + cdda_register_id = -1; + cdda_volume = 100.0; + } + d_scsi_cdrom->set_volume((int)cdda_volume); + break; + case EVENT_FADE_OUT: + if((cdda_volume -= 0.1) <= 0) { + cancel_event(this, cdda_register_id); + cdda_register_id = -1; + cdda_volume = 0.0; + } + d_scsi_cdrom->set_volume((int)cdda_volume); + break; +#endif } } @@ -1630,7 +1909,7 @@ void PC88::event_frame() // update key status memcpy(key_status, emu->get_key_buffer(), sizeof(key_status)); - for(int i = 0; i < 9; i++) { + for(int i = 0; i < array_length(key_conv_table); i++) { // INS or F6-F10 -> SHIFT + DEL or F1-F5 if(key_status[key_conv_table[i][0]]) { key_status[key_conv_table[i][1]] = 1; @@ -1708,6 +1987,88 @@ void PC88::event_vline(int v, int clock) request_intr(IRQ_VRTC, true); update_gvram_wait(); } + // update palette +#if !defined(_PC8001SR) + if(v < (disp_line <= 200 ? 200 : 400)) { +#else + if(v < 200) { +#endif + if(update_palette) { + static bool initialized = false; + static palette_t initial[9] = {0}; + + if(!initialized) { + for(int i = 1; i < 8; i++) { + initial[i].b = (i & 1) ? 7 : 0; + initial[i].r = (i & 2) ? 7 : 0; + initial[i].g = (i & 4) ? 7 : 0; + } + initialized = true; + } + for(int i = 0; i < 9; i++) { + palette_digital[i] = palette_analog[i] = initial[i]; + } +#if defined(_PC8001SR) + if(config.boot_mode != MODE_PC80_V2) { + if(Port31_V1_320x200) { + for(int i = 0; i < 3; i++) { + palette_analog[i].b = (port[0x31] & 4) ? 7 : 0; + palette_analog[i].r = (i & 1) ? 7 : 0; + palette_analog[i].g = (i & 2) ? 7 : 0; + } + palette_analog[3] = palette[8]; + } else if(Port31_V1_MONO) { +// palette_analog[0] = {0, 0, 0}; + palette_analog[1] = palette[8]; + } else { +// for(int i = 1; i < 8; i++) { +// palette_analog[i].b = (i & 1) ? 7 : 0; +// palette_analog[i].r = (i & 2) ? 7 : 0; +// palette_analog[i].g = (i & 4) ? 7 : 0; +// } + palette_analog[0] = palette[8]; + } + if(Port31_V1_320x200) { +// palette_digital[0] = {0, 0, 0}; + } else { + palette_digital[0] = palette_analog[0]; + } + } else { + for(int i = 0; i < 8; i++) { + palette_analog[i].b = (port[0x54 + i] & 1) ? 7 : 0; + palette_analog[i].r = (port[0x54 + i] & 2) ? 7 : 0; + palette_analog[i].g = (port[0x54 + i] & 4) ? 7 : 0; + } + if(!Port31_HCOLOR) { + palette_analog[0] = palette[8]; + } + palette_digital[0] = palette_analog[0]; + } +#else + for(int i = 0; i < 8; i++) { + palette_analog[i] = palette[i]; + } + if(!Port31_HCOLOR) { + if(!Port32_PMODE) { + palette_analog[0] = palette[8]; + } else { + palette_analog[0] = palette[9]; + } + } + palette_digital[0] = palette_analog[0]; +#endif + } + if(v == 0) { + memset(palette_line_changed, 0, sizeof(palette_line_changed)); + } + if((palette_line_changed[v] = (update_palette || v == 0)) == true) { + for(int i = 0; i < 9; i++) { + palette_line_digital[v][i] = palette_digital[i]; + palette_line_analog [v][i] = palette_analog [i]; + } + update_palette = false; + } + } } void PC88::key_down(int code, bool repeat) @@ -1850,8 +2211,8 @@ void PC88::draw_screen() draw_text(); // render graph screen - scrntype_t *palette_pc = palette_graph_pc; bool disp_color_graph = true; + bool draw_scanline_black = config.scan_line; #if defined(_PC8001SR) if(config.boot_mode != MODE_PC80_V2) { if(Port31_V1_320x200) { @@ -1859,163 +2220,214 @@ void PC88::draw_screen() } else if(Port31_V1_MONO) { draw_640x200_mono_graph(); } else { + if(hireso) { + draw_scanline_black = false; + } draw_640x200_attrib_graph(); - palette_pc = palette_text_pc; } + emu->set_vm_screen_lines(200); } else { - if(Port31_COLOR) { + if(Port31_HCOLOR) { if(Port31_320x200) { disp_color_graph = draw_320x200_color_graph(); } else { disp_color_graph = draw_640x200_color_graph(); } + emu->set_vm_screen_lines(200); } else { if(Port31_320x200) { draw_320x200_attrib_graph(); } else { draw_640x200_attrib_graph(); } - palette_pc = palette_text_pc; + if(hireso) { + draw_scanline_black = false; + } + emu->set_vm_screen_lines(200); } } #else if(Port31_HCOLOR) { disp_color_graph = draw_640x200_color_graph(); + emu->set_vm_screen_lines(200); } else if(!Port31_400LINE) { - draw_640x200_mono_graph(); + if(hireso) { + draw_scanline_black = false; + } + draw_640x200_attrib_graph(); +// draw_640x200_mono_graph(); + emu->set_vm_screen_lines(200); } else { + if(hireso) { + draw_scanline_black = false; + } draw_640x400_attrib_graph(); - palette_pc = palette_text_pc; +// draw_640x400_mono_graph(); + emu->set_vm_screen_lines(400); } #endif - // update palette - if(update_palette) { - static const int pex[8] = { - 0, 36, 73, 109, 146, 182, 219, 255 // from m88 - }; - scrntype_t back_color = 0; -#if defined(_PC8001SR) - if(config.boot_mode != MODE_PC80_V2) { - if(Port31_V1_320x200) { - for(int i = 0; i < 3; i++) { - uint8_t b = (port[0x31] & 4) ? 7 : 0; - uint8_t r = (i & 1) ? 7 : 0; - uint8_t g = (i & 2) ? 7 : 0; - palette_graph_pc[i] = RGB_COLOR(pex[r], pex[g], pex[b]); - } - palette_graph_pc[3] = RGB_COLOR(pex[palette[8].r], pex[palette[8].g], pex[palette[8].b]); - } else if(Port31_V1_MONO) { - palette_graph_pc[0] = 0; - palette_graph_pc[1] = RGB_COLOR(pex[palette[8].r], pex[palette[8].g], pex[palette[8].b]); - } else { - back_color = RGB_COLOR(pex[palette[8].r], pex[palette[8].g], pex[palette[8].b]); + // create palette for each scanline +#if !defined(_PC8001SR) + int disp_line = crtc.height * crtc.char_height; + int ymax = (disp_line <= 200) ? 200 : 400; +#else + int ymax = 200; +#endif + static const uint32_t pex[8] = { + 0, 36, 73, 109, 146, 182, 219, 255 // from m88 + }; + scrntype_t palette_digital_text_pc [9]; + scrntype_t palette_analog_text_pc [9]; + scrntype_t palette_digital_graph_pc[9]; + scrntype_t palette_analog_graph_pc [9]; + + scrntype_t palette_line_digital_text_pc [400][9]; + scrntype_t palette_line_analog_graph_pc [400][9]; +#if !defined(_PC8001SR) + scrntype_t palette_line_analog_text_pc [400][9]; + scrntype_t palette_line_digital_graph_pc[400][9]; +#endif + + for(int y = 0; y < ymax; y++) { + if(palette_line_changed[y]) { + for(int i = 0; i < 9; i++) { + // A is a flag for crt filter + palette_digital_text_pc [i] = RGBA_COLOR(pex[palette_line_digital[y][i].r], pex[palette_line_digital[y][i].g], pex[palette_line_digital[y][i].b], 255); + palette_analog_text_pc [i] = RGBA_COLOR(pex[palette_line_analog [y][i].r], pex[palette_line_analog [y][i].g], pex[palette_line_analog [y][i].b], 255); + palette_digital_graph_pc[i] = RGBA_COLOR(pex[palette_line_digital[y][i].r], pex[palette_line_digital[y][i].g], pex[palette_line_digital[y][i].b], 0); + palette_analog_graph_pc [i] = RGBA_COLOR(pex[palette_line_analog [y][i].r], pex[palette_line_analog [y][i].g], pex[palette_line_analog [y][i].b], 0); } - } else { - if(Port31_COLOR) { - for(int i = 0; i < 8; i++) { - uint8_t b = (port[0x54 + i] & 1) ? 7 : 0; - uint8_t r = (port[0x54 + i] & 2) ? 7 : 0; - uint8_t g = (port[0x54 + i] & 4) ? 7 : 0; - palette_graph_pc[i] = RGB_COLOR(pex[r], pex[g], pex[b]); - } - back_color = palette_graph_pc[0]; - } else { - back_color = RGB_COLOR(pex[palette[8].r], pex[palette[8].g], pex[palette[8].b]); + // set back color to black if cg screen is off in color mode + if(!disp_color_graph) { + palette_digital_text_pc [0] = + palette_analog_text_pc [0] = + palette_digital_graph_pc[0] = + palette_analog_graph_pc [0] = 0; } - } -#else - if(Port31_HCOLOR) { - for(int i = 0; i < 8; i++) { - palette_graph_pc[i] = RGB_COLOR(pex[palette[i].r], pex[palette[i].g], pex[palette[i].b]); + palette_analog_text_pc [8] = palette_digital_text_pc [0]; + palette_analog_graph_pc[8] = palette_digital_graph_pc[0]; + } + if(ymax == 200) { + for(int i = 0; i < 9; i++) { + palette_line_digital_text_pc [2 * y ][i] = + palette_line_digital_text_pc [2 * y + 1][i] = palette_digital_text_pc [i]; + palette_line_analog_graph_pc [2 * y ][i] = + palette_line_analog_graph_pc [2 * y + 1][i] = palette_analog_graph_pc [i]; +#if !defined(_PC8001SR) + palette_line_analog_text_pc [2 * y ][i] = + palette_line_analog_text_pc [2 * y + 1][i] = palette_analog_text_pc [i]; + palette_line_digital_graph_pc[2 * y ][i] = + palette_line_digital_graph_pc[2 * y + 1][i] = palette_digital_graph_pc[i]; +#endif } - } else if(!Port31_400LINE) { - palette_graph_pc[0] = RGB_COLOR(pex[palette[8].r], pex[palette[8].g], pex[palette[8].b]); - palette_graph_pc[1] = RGB_COLOR(255, 255, 255); - } - back_color = RGB_COLOR(pex[palette[8].r], pex[palette[8].g], pex[palette[8].b]); + } else { + for(int i = 0; i < 9; i++) { + palette_line_digital_text_pc [y][i] = palette_digital_text_pc [i]; + palette_line_analog_graph_pc [y][i] = palette_analog_graph_pc [i]; +#if !defined(_PC8001SR) + palette_line_analog_text_pc [y][i] = palette_analog_text_pc [i]; + palette_line_digital_graph_pc[y][i] = palette_digital_graph_pc[i]; #endif - // back color for attrib mode - palette_text_pc[0] = back_color; - update_palette = false; - } - - // set back color to black if cg screen is off in color mode - scrntype_t palette_text_back = palette_text_pc[0]; - scrntype_t palette_graph_back = palette_graph_pc[0]; - - if(!disp_color_graph) { - palette_text_pc[0] = palette_graph_pc[0] = 0; + } + } } // copy to screen buffer #if !defined(_PC8001SR) - if(!Port31_400LINE) { -#endif - for(int y = 0; y < 200; y++) { - // for Xak2 opening (XM8 version 1.00) -/* - if(crtc.char_height == 0x10) { - if(y >= (crtc.height * crtc.char_height / 2)) { - while(y < 200) { - scrntype_t* dest0 = emu->get_screen_buffer(y * 2); - scrntype_t* dest1 = emu->get_screen_buffer(y * 2 + 1); - memset(dest0, 0, sizeof(scrntype_t) * 640); - memset(dest1, 0, sizeof(scrntype_t) * 640); - y++; - } - break; - } +#if defined(SUPPORT_PC88_VAB) + // X88000 + if(PortB4_VAB_DISP) { + uint8_t *src = &exram[(0x8000 * 4) * PC88_VAB_PAGE]; + + for(int y = 0; y < 400; y += 2) { + scrntype_t* dest0 = emu->get_screen_buffer(y); + scrntype_t* dest1 = emu->get_screen_buffer(y + 1); + + for(int x = 0; x < 640; x += 2) { + pair16_t c; + c.b.l = *src++; + c.b.h = *src++; + dest0[x] = dest0[x + 1] = palette_vab_pc[c.w]; } -*/ - scrntype_t* dest0 = emu->get_screen_buffer(y * 2); - scrntype_t* dest1 = emu->get_screen_buffer(y * 2 + 1); - uint8_t* src_t = text[y]; + if(config.scan_line) { + memset(dest1, 0, sizeof(scrntype_t) * 640); + } else { + memcpy(dest1, dest0, sizeof(scrntype_t) * 640); + } + } + emu->screen_skip_line(true); + } else +#endif + if(!Port31_HCOLOR && Port31_400LINE) { + for(int y = 0; y < 400; y++) { + scrntype_t* dest = emu->get_screen_buffer(y); + uint8_t* src_t = text[y >> 1]; uint8_t* src_g = graph[y]; + scrntype_t* pal_t; + scrntype_t* pal_g; +// if(Port31_HCOLOR) { +// pal_t = palette_line_digital_text_pc [y]; +// pal_g = palette_line_analog_graph_pc [y]; +// } else + if(Port32_PMODE) { + pal_t = palette_line_analog_text_pc [y]; + pal_g = palette_line_analog_graph_pc [y]; + } else { + pal_t = palette_line_digital_text_pc [y]; + pal_g = palette_line_digital_graph_pc[y]; + } + for(int x = 0; x < 640; x++) { + uint32_t t = src_t[x]; + dest[x] = t ? pal_t[t] : pal_g[src_g[x]]; + } + } + emu->screen_skip_line(false); + } else +#endif + { + for(int y = 0; y < 400; y++) { + scrntype_t* dest = emu->get_screen_buffer(y); + uint8_t* src_t = text[y >> 1]; + uint8_t* src_g = graph[y]; + scrntype_t* pal_t; + scrntype_t* pal_g; #if defined(_PC8001SR) + pal_t = palette_line_digital_text_pc[y]; + pal_g = palette_line_analog_graph_pc[y]; + if(port[0x33] & 8) { for(int x = 0; x < 640; x++) { + uint32_t t = src_t[x]; uint32_t g = src_g[x]; - dest0[x] = g ? palette_pc[g] : palette_text_pc[src_t[x]]; + dest[x] = (!g && t) ? pal_t[t] : ((y & 1) && draw_scanline_black) ? 0 : pal_g[g]; } } else { -#endif for(int x = 0; x < 640; x++) { uint32_t t = src_t[x]; - dest0[x] = t ? palette_text_pc[t] : palette_pc[src_g[x]]; + dest[x] = t ? pal_t[t] : ((y & 1) && draw_scanline_black) ? 0 : pal_g[src_g[x]]; } -#if defined(_PC8001SR) } -#endif - if(config.scan_line) { - memset(dest1, 0, 640 * sizeof(scrntype_t)); +#else + if(Port31_HCOLOR) { + pal_t = palette_line_digital_text_pc [y]; + pal_g = palette_line_analog_graph_pc [y]; + } else if(Port32_PMODE) { + pal_t = palette_line_analog_text_pc [y]; + pal_g = palette_line_analog_graph_pc [y]; } else { - for(int x = 0; x < 640; x++) { - dest1[x] = dest0[x]; - } + pal_t = palette_line_digital_text_pc [y]; + pal_g = palette_line_digital_graph_pc[y]; } - } - emu->screen_skip_line(true); -#if !defined(_PC8001SR) - } else { - for(int y = 0; y < 400; y++) { - scrntype_t* dest = emu->get_screen_buffer(y); - uint8_t* src_t = text[y >> 1]; - uint8_t* src_g = graph[y]; - for(int x = 0; x < 640; x++) { uint32_t t = src_t[x]; - dest[x] = t ? palette_text_pc[t] : palette_pc[src_g[x]]; + dest[x] = t ? pal_t[t] : ((y & 1) && draw_scanline_black) ? 0 : pal_g[src_g[x]]; } +#endif } - emu->screen_skip_line(false); + emu->screen_skip_line(true); } -#endif - - // restore back color palette - palette_text_pc[0] = palette_text_back; - palette_graph_pc[0] = palette_graph_back; } /* @@ -2033,29 +2445,33 @@ void PC88::draw_screen() void PC88::draw_text() { - uint8_t ct = 0; - if(crtc.status & 0x88) { + // dma underrun crtc.status &= ~0x80; - ct = crtc.reverse ? 3 : 2; + memset(crtc.text.expand, 0, 200 * 80); + memset(crtc.attrib.expand, crtc.reverse ? 3 : 2, 200 * 80); } // for Advanced Fantasian Opening (20line) (XM8 version 1.00) if(!(crtc.status & 0x10) || Port53_TEXTDS) { // if(!(crtc.status & 0x10) || (crtc.status & 8) || Port53_TEXTDS) { -// memset(text, 0, sizeof(text)); -// return; - ct = 2; - } - if(ct) { memset(crtc.text.expand, 0, 200 * 80); - memset(crtc.attrib.expand, ct, 200 * 80); + for(int y = 0; y < 200; y++) { + for(int x = 0; x < 80; x++) { + crtc.attrib.expand[y][x] &= 0xe0; + crtc.attrib.expand[y][x] |= 0x02; + } + } +// memset(crtc.attrib.expand, 2, 200 * 80); } // for Xak2 opening memset(text, 8, sizeof(text)); + memset(text_color, 7, sizeof(text_color)); + memset(text_reverse, 0, sizeof(text_reverse)); int char_height = crtc.char_height; uint8_t color_mask = Port30_COLOR ? 0 : 7; + uint8_t code_expand, attr_expand; if(!hireso) { char_height <<= 1; @@ -2070,16 +2486,30 @@ void PC88::draw_text() for(int cy = 0, ytop = 0; cy < crtc.height && ytop < 400; cy++, ytop += char_height) { for(int x = 0, cx = 0; cx < crtc.width; x += 8, cx++) { if(Port30_40 && (cx & 1)) { - continue; + // don't update code/attrib + } else { + code_expand = crtc.text.expand[cy][cx]; + attr_expand = crtc.attrib.expand[cy][cx]; } - uint8_t attrib = crtc.attrib.expand[cy][cx]; + uint8_t attrib = attr_expand;//crtc.attrib.expand[cy][cx]; +// uint8_t color = !(Port30_COLOR && (attrib & 8)) ? 7 : (attrib & 0xe0) ? (attrib >> 5) : 8; uint8_t color = (attrib & 0xe0) ? ((attrib >> 5) | color_mask) : 8; bool under_line = ((attrib & 8) != 0); bool upper_line = ((attrib & 4) != 0); bool secret = ((attrib & 2) != 0); bool reverse = ((attrib & 1) != 0); - uint8_t code = secret ? 0 : crtc.text.expand[cy][cx]; + uint8_t color_tmp = color; + bool reverse_tmp = reverse; + + // from ePC-8801MA‰ü + if(Port31_GRAPH && !Port31_HCOLOR) { + if(reverse) { + reverse = false; + color = 8; + } + } + uint8_t code = secret ? 0 : code_expand;//crtc.text.expand[cy][cx]; #ifdef SUPPORT_PC88_PCG8100 uint8_t *pattern = ((attrib & 0x10) ? sg_pattern : pcg_pattern) + code * 8; #else @@ -2088,33 +2518,33 @@ void PC88::draw_text() for(int l = 0, y = ytop; l < char_height / 2 && y < 400; l++, y += 2) { uint8_t pat = (l < 8) ? pattern[l] : 0; + + if(Port30_40) { + // from ePC-8801MA‰ü + static const uint8_t wct[16] = { + 0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f, 0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff + }; + pat = wct[(cx & 1) ? (pat & 0x0f) : (pat >> 4)]; + } if((upper_line && l == 0) || (under_line && l >= 7)) { pat = 0xff; } if(reverse) { - pat = ~pat; + pat ^= 0xff; } - uint8_t *dest = &text[y >> 1][x]; - if(Port30_40) { - dest[ 0] = dest[ 1] = (pat & 0x80) ? color : 0; - dest[ 2] = dest[ 3] = (pat & 0x40) ? color : 0; - dest[ 4] = dest[ 5] = (pat & 0x20) ? color : 0; - dest[ 6] = dest[ 7] = (pat & 0x10) ? color : 0; - dest[ 8] = dest[ 9] = (pat & 0x08) ? color : 0; - dest[10] = dest[11] = (pat & 0x04) ? color : 0; - dest[12] = dest[13] = (pat & 0x02) ? color : 0; - dest[14] = dest[15] = (pat & 0x01) ? color : 0; - } else { - dest[0] = (pat & 0x80) ? color : 0; - dest[1] = (pat & 0x40) ? color : 0; - dest[2] = (pat & 0x20) ? color : 0; - dest[3] = (pat & 0x10) ? color : 0; - dest[4] = (pat & 0x08) ? color : 0; - dest[5] = (pat & 0x04) ? color : 0; - dest[6] = (pat & 0x02) ? color : 0; - dest[7] = (pat & 0x01) ? color : 0; - } + dest[0] = (pat & 0x80) ? color : 0; + dest[1] = (pat & 0x40) ? color : 0; + dest[2] = (pat & 0x20) ? color : 0; + dest[3] = (pat & 0x10) ? color : 0; + dest[4] = (pat & 0x08) ? color : 0; + dest[5] = (pat & 0x04) ? color : 0; + dest[6] = (pat & 0x02) ? color : 0; + dest[7] = (pat & 0x01) ? color : 0; + + // store text attributes for monocolor graph screen + text_color[y >> 1][cx] = color_tmp; + text_reverse[y >> 1][cx] = reverse_tmp; } } } @@ -2142,7 +2572,7 @@ bool PC88::draw_320x200_color_graph() tmp = gvram_g0; gvram_g0 = gvram_g1; gvram_g1 = tmp; } - for(int y = 0, addr = 0; y < 200; y++) { + for(int y = 0, addr = 0; y < 400; y += 2) { for(int x = 0; x < 640; x += 16) { uint8_t b0 = gvram_b0[addr]; uint8_t r0 = gvram_r0[addr]; @@ -2178,6 +2608,11 @@ bool PC88::draw_320x200_color_graph() brg1 = ((b1 & 0x01) ) | ((r1 & 0x01) << 1) | ((g1 & 0x01) << 2); dest[14] = dest[15] = brg0 ? brg0 : brg1; } + if(config.scan_line) { + memset(graph[y + 1], 0, 640); + } else { + memcpy(graph[y + 1], graph[y], 640); + } } return true; } @@ -2192,7 +2627,7 @@ bool PC88::draw_320x200_4color_graph() uint8_t *gvram_r = Port53_G1DS ? gvram_null : (gvram + 0x4000); uint8_t *gvram_g = Port53_G2DS ? gvram_null : (gvram + 0x8000); - for(int y = 0, addr = 0; y < 200; y++) { + for(int y = 0, addr = 0; y < 400; y += 2) { for(int x = 0; x < 640; x += 8) { uint8_t brg = gvram_b[addr] | gvram_r[addr] | gvram_g[addr]; addr++; @@ -2202,6 +2637,11 @@ bool PC88::draw_320x200_4color_graph() dest[4] = dest[5] = (brg >> 2) & 3; dest[6] = dest[7] = (brg ) & 3; } + if(config.scan_line) { + memset(graph[y + 1], 0, 640); + } else { + memcpy(graph[y + 1], graph[y], 640); + } } return true; } @@ -2219,49 +2659,89 @@ void PC88::draw_320x200_attrib_graph() uint8_t *gvram_r1 = Port53_G4DS ? gvram_null : (gvram + 0x6000); uint8_t *gvram_g1 = Port53_G5DS ? gvram_null : (gvram + 0xa000); - int char_height = crtc.char_height ? crtc.char_height : 8; - uint8_t color_mask = Port30_COLOR ? 0 : 7; - if(Port30_40) { - for(int y = 0, addr = 0; y < 200; y++) { - int cy = y / char_height; + for(int y = 0, addr = 0; y < 400; y += 2) { for(int x = 0, cx = 0; x < 640; x += 16, cx += 2) { - uint8_t attrib = crtc.attrib.expand[cy][cx]; - uint8_t color = (attrib & 0xe0) ? ((attrib >> 5) | color_mask) : 8; - uint8_t brg = gvram_b0[addr] | gvram_r0[addr] | gvram_g0[addr] | - gvram_b1[addr] | gvram_r1[addr] | gvram_g1[addr]; + uint8_t color = text_color[y >> 1][cx]; + uint8_t brg0 = gvram_b0[addr] | gvram_r0[addr] | gvram_g0[addr] | + gvram_b1[addr] | gvram_r1[addr] | gvram_g1[addr]; + uint8_t brg1 = 0; + if(text_reverse[y >> 1][cx]) { + brg0 ^= 0xff; + brg1 ^= 0xff; + } addr++; - uint8_t *dest = &graph[y][x]; - dest[ 0] = dest[ 1] = (brg & 0x80) ? color : 0; - dest[ 2] = dest[ 3] = (brg & 0x40) ? color : 0; - dest[ 4] = dest[ 5] = (brg & 0x20) ? color : 0; - dest[ 6] = dest[ 7] = (brg & 0x10) ? color : 0; - dest[ 8] = dest[ 9] = (brg & 0x08) ? color : 0; - dest[10] = dest[11] = (brg & 0x04) ? color : 0; - dest[12] = dest[13] = (brg & 0x02) ? color : 0; - dest[14] = dest[15] = (brg & 0x01) ? color : 0; + uint8_t *dest0 = &graph[y ][x]; + uint8_t *dest1 = &graph[y + 1][x]; + dest0[ 0] = dest0[ 1] = (brg0 & 0x80) ? color : 0; + dest0[ 2] = dest0[ 3] = (brg0 & 0x40) ? color : 0; + dest0[ 4] = dest0[ 5] = (brg0 & 0x20) ? color : 0; + dest0[ 6] = dest0[ 7] = (brg0 & 0x10) ? color : 0; + dest0[ 8] = dest0[ 9] = (brg0 & 0x08) ? color : 0; + dest0[10] = dest0[11] = (brg0 & 0x04) ? color : 0; + dest0[12] = dest0[13] = (brg0 & 0x02) ? color : 0; + dest0[14] = dest0[15] = (brg0 & 0x01) ? color : 0; + if(!hireso) continue; + dest1[ 0] = dest1[ 1] = (brg1 & 0x80) ? color : 0; + dest1[ 2] = dest1[ 3] = (brg1 & 0x40) ? color : 0; + dest1[ 4] = dest1[ 5] = (brg1 & 0x20) ? color : 0; + dest1[ 6] = dest1[ 7] = (brg1 & 0x10) ? color : 0; + dest1[ 8] = dest1[ 9] = (brg1 & 0x08) ? color : 0; + dest1[10] = dest1[11] = (brg1 & 0x04) ? color : 0; + dest1[12] = dest1[13] = (brg1 & 0x02) ? color : 0; + dest1[14] = dest1[15] = (brg1 & 0x01) ? color : 0; + } + if(!hireso) { + if(config.scan_line) { + memset(graph[y + 1], 0, 640); + } else { + memcpy(graph[y + 1], graph[y], 640); + } } } } else { - for(int y = 0, addr = 0; y < 200; y++) { - int cy = y / char_height; + for(int y = 0, addr = 0; y < 400; y += 2) { for(int x = 0, cx = 0; x < 640; x += 16, cx += 2) { - uint8_t attrib_l = crtc.attrib.expand[cy][cx]; - uint8_t color_l = (attrib_l & 0xe0) ? ((attrib_l >> 5) | color_mask) : 8; - uint8_t attrib_r = crtc.attrib.expand[cy][cx + 1]; - uint8_t color_r = (attrib_r & 0xe0) ? ((attrib_r >> 5) | color_mask) : 8; - uint8_t brg = gvram_b0[addr] | gvram_r0[addr] | gvram_g0[addr] | - gvram_b1[addr] | gvram_r1[addr] | gvram_g1[addr]; + uint8_t color_l = text_color[y >> 1][cx + 0]; + uint8_t color_r = text_color[y >> 1][cx + 1]; + uint8_t brg0 = gvram_b0[addr] | gvram_r0[addr] | gvram_g0[addr] | + gvram_b1[addr] | gvram_r1[addr] | gvram_g1[addr]; + uint8_t brg1 = 0; + if(text_reverse[y >> 1][cx + 0]) { + brg0 ^= 0xf0; + brg0 ^= 0xf0; + } + if(text_reverse[y >> 1][cx + 1]) { + brg1 ^= 0x0f; + brg1 ^= 0x0f; + } addr++; - uint8_t *dest = &graph[y][x]; - dest[ 0] = dest[ 1] = (brg & 0x80) ? color_l : 0; - dest[ 2] = dest[ 3] = (brg & 0x40) ? color_l : 0; - dest[ 4] = dest[ 5] = (brg & 0x20) ? color_l : 0; - dest[ 6] = dest[ 7] = (brg & 0x10) ? color_l : 0; - dest[ 8] = dest[ 9] = (brg & 0x08) ? color_r : 0; - dest[10] = dest[11] = (brg & 0x04) ? color_r : 0; - dest[12] = dest[13] = (brg & 0x02) ? color_r : 0; - dest[14] = dest[15] = (brg & 0x01) ? color_r : 0; + uint8_t *dest0 = &graph[y ][x]; + uint8_t *dest1 = &graph[y + 1][x]; + dest0[ 0] = dest0[ 1] = (brg0 & 0x80) ? color_l : 0; + dest0[ 2] = dest0[ 3] = (brg0 & 0x40) ? color_l : 0; + dest0[ 4] = dest0[ 5] = (brg0 & 0x20) ? color_l : 0; + dest0[ 6] = dest0[ 7] = (brg0 & 0x10) ? color_l : 0; + dest0[ 8] = dest0[ 9] = (brg0 & 0x08) ? color_r : 0; + dest0[10] = dest0[11] = (brg0 & 0x04) ? color_r : 0; + dest0[12] = dest0[13] = (brg0 & 0x02) ? color_r : 0; + dest0[14] = dest0[15] = (brg0 & 0x01) ? color_r : 0; + if(!hireso) continue; + dest1[ 0] = dest1[ 1] = (brg1 & 0x80) ? color_l : 0; + dest1[ 2] = dest1[ 3] = (brg1 & 0x40) ? color_l : 0; + dest1[ 4] = dest1[ 5] = (brg1 & 0x20) ? color_l : 0; + dest1[ 6] = dest1[ 7] = (brg1 & 0x10) ? color_l : 0; + dest1[ 8] = dest1[ 9] = (brg1 & 0x08) ? color_r : 0; + dest1[10] = dest1[11] = (brg1 & 0x04) ? color_r : 0; + dest1[12] = dest1[13] = (brg1 & 0x02) ? color_r : 0; + dest1[14] = dest1[15] = (brg1 & 0x01) ? color_r : 0; + } + if(!hireso) { + if(config.scan_line) { + memset(graph[y + 1], 0, 640); + } else { + memcpy(graph[y + 1], graph[y], 640); + } } } } @@ -2282,7 +2762,7 @@ bool PC88::draw_640x200_color_graph() uint8_t *gvram_r = /*Port53_G1DS ? gvram_null : */(gvram + 0x4000); uint8_t *gvram_g = /*Port53_G2DS ? gvram_null : */(gvram + 0x8000); - for(int y = 0, addr = 0; y < 200; y++) { + for(int y = 0, addr = 0; y < 400; y += 2) { for(int x = 0; x < 640; x += 8) { uint8_t b = gvram_b[addr]; uint8_t r = gvram_r[addr]; @@ -2298,6 +2778,11 @@ bool PC88::draw_640x200_color_graph() dest[6] = ((b & 0x02) >> 1) | ((r & 0x02) ) | ((g & 0x02) << 1); dest[7] = ((b & 0x01) ) | ((r & 0x01) << 1) | ((g & 0x01) << 2); } + if(config.scan_line) { + memset(graph[y + 1], 0, 640); + } else { + memcpy(graph[y + 1], graph[y], 640); + } } return true; } @@ -2312,7 +2797,7 @@ void PC88::draw_640x200_mono_graph() uint8_t *gvram_r = Port53_G1DS ? gvram_null : (gvram + 0x4000); uint8_t *gvram_g = Port53_G2DS ? gvram_null : (gvram + 0x8000); - for(int y = 0, addr = 0; y < 200; y++) { + for(int y = 0, addr = 0; y < 400; y += 2) { for(int x = 0; x < 640; x += 8) { uint8_t brg = gvram_b[addr] | gvram_r[addr] | gvram_g[addr]; addr++; @@ -2326,10 +2811,14 @@ void PC88::draw_640x200_mono_graph() dest[6] = (brg & 0x02) >> 1; dest[7] = (brg & 0x01) ; } + if(config.scan_line) { + memset(graph[y + 1], 0, 640); + } else { + memcpy(graph[y + 1], graph[y], 640); + } } } -#if defined(_PC8001SR) void PC88::draw_640x200_attrib_graph() { if(!Port31_GRAPH || (Port53_G0DS && Port53_G1DS && Port53_G2DS)) { @@ -2340,33 +2829,88 @@ void PC88::draw_640x200_attrib_graph() uint8_t *gvram_r = Port53_G1DS ? gvram_null : (gvram + 0x4000); uint8_t *gvram_g = Port53_G2DS ? gvram_null : (gvram + 0x8000); - int char_height = crtc.char_height ? crtc.char_height : 8; - uint8_t color_mask = Port30_COLOR ? 0 : 7, color; - - for(int y = 0, addr = 0; y < 200; y++) { - int cy = y / char_height; + for(int y = 0, addr = 0; y < 400; y += 2) { for(int x = 0, cx = 0; x < 640; x += 8, cx++) { - if(Port30_40 && (cx & 1)) { - // don't update color + uint8_t color = text_color[y >> 1][cx]; + uint8_t brg0 = gvram_b[addr] | gvram_r[addr] | gvram_g[addr]; + uint8_t brg1 = 0; + if(text_reverse[y >> 1][cx]) { + brg0 ^= 0xff; + brg1 ^= 0xff; + } + addr++; + uint8_t *dest0 = &graph[y ][x]; + uint8_t *dest1 = &graph[y + 1][x]; + dest0[0] = (brg0 & 0x80) ? color : 0; + dest0[1] = (brg0 & 0x40) ? color : 0; + dest0[2] = (brg0 & 0x20) ? color : 0; + dest0[3] = (brg0 & 0x10) ? color : 0; + dest0[4] = (brg0 & 0x08) ? color : 0; + dest0[5] = (brg0 & 0x04) ? color : 0; + dest0[6] = (brg0 & 0x02) ? color : 0; + dest0[7] = (brg0 & 0x01) ? color : 0; + if(!hireso) continue; + dest1[0] = (brg1 & 0x80) ? color : 0; + dest1[1] = (brg1 & 0x40) ? color : 0; + dest1[2] = (brg1 & 0x20) ? color : 0; + dest1[3] = (brg1 & 0x10) ? color : 0; + dest1[4] = (brg1 & 0x08) ? color : 0; + dest1[5] = (brg1 & 0x04) ? color : 0; + dest1[6] = (brg1 & 0x02) ? color : 0; + dest1[7] = (brg1 & 0x01) ? color : 0; + } + if(!hireso) { + if(config.scan_line) { + memset(graph[y + 1], 0, 640); } else { - uint8_t attrib = crtc.attrib.expand[cy][cx]; - color = (attrib & 0xe0) ? ((attrib >> 5) | color_mask) : 8; + memcpy(graph[y + 1], graph[y], 640); } - uint8_t brg = gvram_b[addr] | gvram_r[addr] | gvram_g[addr]; + } + } +} + +#if !defined(_PC8001SR) +void PC88::draw_640x400_mono_graph() +{ + if(!Port31_GRAPH || (Port53_G0DS && Port53_G1DS)) { + memset(graph, 0, sizeof(graph)); + return; + } + uint8_t *gvram_b = Port53_G0DS ? gvram_null : (gvram + 0x0000); + uint8_t *gvram_r = Port53_G1DS ? gvram_null : (gvram + 0x4000); + + for(int y = 0, addr = 0; y < 200; y++) { + for(int x = 0; x < 640; x += 8) { + uint8_t b = gvram_b[addr]; addr++; uint8_t *dest = &graph[y][x]; - dest[0] = (brg & 0x80) ? color : 0; - dest[1] = (brg & 0x40) ? color : 0; - dest[2] = (brg & 0x20) ? color : 0; - dest[3] = (brg & 0x10) ? color : 0; - dest[4] = (brg & 0x08) ? color : 0; - dest[5] = (brg & 0x04) ? color : 0; - dest[6] = (brg & 0x02) ? color : 0; - dest[7] = (brg & 0x01) ? color : 0; + dest[0] = (b & 0x80) >> 7; + dest[1] = (b & 0x40) >> 6; + dest[2] = (b & 0x20) >> 5; + dest[3] = (b & 0x10) >> 4; + dest[4] = (b & 0x08) >> 3; + dest[5] = (b & 0x04) >> 2; + dest[6] = (b & 0x02) >> 1; + dest[7] = (b & 0x01) ; + } + } + for(int y = 200, addr = 0; y < 400; y++) { + for(int x = 0; x < 640; x += 8) { + uint8_t r = gvram_r[addr]; + addr++; + uint8_t *dest = &graph[y][x]; + dest[0] = (r & 0x80) >> 7; + dest[1] = (r & 0x40) >> 6; + dest[2] = (r & 0x20) >> 5; + dest[3] = (r & 0x10) >> 4; + dest[4] = (r & 0x08) >> 3; + dest[5] = (r & 0x04) >> 2; + dest[6] = (r & 0x02) >> 1; + dest[7] = (r & 0x01) ; } } } -#else + void PC88::draw_640x400_attrib_graph() { if(!Port31_GRAPH || (Port53_G0DS && Port53_G1DS)) { @@ -2376,21 +2920,13 @@ void PC88::draw_640x400_attrib_graph() uint8_t *gvram_b = Port53_G0DS ? gvram_null : (gvram + 0x0000); uint8_t *gvram_r = Port53_G1DS ? gvram_null : (gvram + 0x4000); - int char_height = crtc.char_height ? crtc.char_height : 16; - uint8_t color_mask = Port30_COLOR ? 0 : 7, color; - for(int y = 0, addr = 0; y < 200; y++) { - int cy = y / char_height; for(int x = 0, cx = 0; x < 640; x += 8, cx++) { - if(Port30_40 && (cx & 1)) { - // don't update color - } else { - uint8_t attrib = crtc.attrib.expand[cy][cx]; - // for SORCERIAN music library (XM8 version 1.20) - color = (attrib >> 5) | color_mask; -// color = (attrib & 0xe0) ? ((attrib >> 5) | color_mask) : 8; - } + uint8_t color = text_color[y >> 1][cx]; uint8_t b = gvram_b[addr]; + if(text_reverse[y >> 1][cx]) { + b ^= 0xff; + } addr++; uint8_t *dest = &graph[y][x]; dest[0] = (b & 0x80) ? color : 0; @@ -2404,17 +2940,12 @@ void PC88::draw_640x400_attrib_graph() } } for(int y = 200, addr = 0; y < 400; y++) { - int cy = y / char_height; for(int x = 0, cx = 0; x < 640; x += 8, cx++) { - if(Port30_40 && (cx & 1)) { - // don't update color - } else { - uint8_t attrib = crtc.attrib.expand[cy][cx]; - // for SORCERIAN music library (XM8 version 1.20) - color = (attrib >> 5) | color_mask; -// color = (attrib & 0xe0) ? ((attrib >> 5) | color_mask) : 8; - } + uint8_t color = text_color[y >> 1][cx]; uint8_t r = gvram_r[addr]; + if(text_reverse[y >> 1][cx]) { + r ^= 0xff; + } addr++; uint8_t *dest = &graph[y][x]; dest[0] = (r & 0x80) ? color : 0; @@ -2483,7 +3014,6 @@ void pc88_crtc_t::reset(bool hireso) cursor.type = cursor.mode = -1; cursor.x = cursor.y = -1; attrib.data = 0xe0; - attrib.mask = 0xff; attrib.num = 20; width = 80; height = 25; @@ -2688,7 +3218,7 @@ void pc88_crtc_t::expand_buffer(bool hireso, bool line400) for(int cy = 0, ytop = 0, ofs = 0; cy < height && ytop < 200; cy++, ytop += char_height_tmp, ofs += 80 + attrib.num * 2) { for(int cx = 0; cx < width; cx += 2) { set_attrib(read_buffer(ofs + cx + 1)); - attrib.expand[cy][cx] = attrib.expand[cy][cx + 1] = attrib.data & attrib.mask; + attrib.expand[cy][cx] = attrib.expand[cy][cx + 1] = attrib.data; } if((status & 8) && exitline == -1) { exitline = cy; @@ -2706,12 +3236,14 @@ void pc88_crtc_t::expand_buffer(bool hireso, bool line400) for(int i = 2 * (attrib.num - 1); i >= 0; i -= 2) { flags[read_buffer(ofs + i + 80) & 0x7f] = 1; } + attrib.data &= 0xf3; // for PC-8801mkIIFR •t‘®ƒfƒ‚ + for(int cx = 0, pos = 0; cx < width; cx++) { if(flags[cx]) { set_attrib(read_buffer(ofs + pos + 81)); pos += 2; } - attrib.expand[cy][cx] = attrib.data & attrib.mask; + attrib.expand[cy][cx] = attrib.data; } if((status & 8) && exitline == -1) { exitline = cy; @@ -2733,7 +3265,13 @@ underrun: if(exitline != -1) { for(int cy = exitline; cy < 200; cy++) { memset(&text.expand[cy][0], 0, width); - memset(&attrib.expand[cy][0], 0, width); +#if 1 + // SORCERIAN Music Library ver-2.1 + memset(&attrib.expand[cy][0], 0xe0, width); // color=7 +#else + // from ePC-8801MA‰ü + memset(&attrib.expand[cy][0], 0x00, width); +#endif } } } @@ -2744,18 +3282,15 @@ void pc88_crtc_t::set_attrib(uint8_t code) // color if(code & 8) { attrib.data = (attrib.data & 0x0f) | (code & 0xf0); - attrib.mask = 0xf3; //for PC-8801mkIIFR •t‘®ƒfƒ‚ } else { attrib.data = (attrib.data & 0xf0) | ((code >> 2) & 0x0d) | ((code << 1) & 2); attrib.data ^= reverse; attrib.data ^= ((code & 2) && !(code & 1)) ? blink.attrib : 0; - attrib.mask = 0xff; } } else { attrib.data = 0xe0 | ((code >> 3) & 0x10) | ((code >> 2) & 0x0d) | ((code << 1) & 2); attrib.data ^= reverse; attrib.data ^= ((code & 2) && !(code & 1)) ? blink.attrib : 0; - attrib.mask = 0xff; } } @@ -2780,8 +3315,10 @@ void pc88_dmac_t::write_io8(uint32_t addr, uint32_t data) } else { if((mode & 0x80) && c == 2) { ch[3].addr.b.h = data; + ch[3].addr.b.h2 = ch[3].addr.b.h3 = 0; } ch[c].addr.b.h = data; + ch[c].addr.b.h2 = ch[c].addr.b.h3 = 0; } high_low = !high_low; break; @@ -2797,9 +3334,11 @@ void pc88_dmac_t::write_io8(uint32_t addr, uint32_t data) } else { if((mode & 0x80) && c == 2) { ch[3].count.b.h = data & 0x3f; + ch[3].count.b.h2 = ch[3].count.b.h3 = 0; ch[3].mode = data & 0xc0; } ch[c].count.b.h = data & 0x3f; + ch[c].count.b.h2 = ch[c].count.b.h3 = 0; ch[c].mode = data & 0xc0; } high_low = !high_low; @@ -2862,15 +3401,20 @@ void pc88_dmac_t::run(int c, int nbytes) { if(ch[c].running) { while(nbytes > 0 && ch[c].count.sd >= 0) { -// if(ch[c].mode == 0x80) { + if(ch[c].mode == 0x80) { ch[c].io->write_dma_io8(0, mem->read_dma_data8(ch[c].addr.w.l)); -// } else if(ch[c].mode == 0x40) { -// mem->write_dma_data8(ch[c].addr.w.l, ch[c].io->read_dma_io8(0)); -// } + } else if(ch[c].mode == 0x40) { + mem->write_dma_data8(ch[c].addr.w.l, ch[c].io->read_dma_io8(0)); + } else if(ch[c].mode == 0x00) { + ch[c].io->read_dma_io8(0); // verify + } ch[c].addr.sd++; ch[c].count.sd--; nbytes--; } + if(ch[c].count.sd < 0) { + finish(c); + } } } @@ -2878,11 +3422,13 @@ void pc88_dmac_t::finish(int c) { if(ch[c].running) { while(ch[c].count.sd >= 0) { -// if(ch[c].mode == 0x80) { + if(ch[c].mode == 0x80) { ch[c].io->write_dma_io8(0, mem->read_dma_data8(ch[c].addr.w.l)); -// } else if(ch[c].mode == 0x40) { -// mem->write_dma_data8(ch[c].addr.w.l, ch[c].io->read_dma_io8(0)); -// } + } else if(ch[c].mode == 0x40) { + mem->write_dma_data8(ch[c].addr.w.l, ch[c].io->read_dma_io8(0)); + } else if(ch[c].mode == 0x00) { + ch[c].io->read_dma_io8(0); // verify + } ch[c].addr.sd++; ch[c].count.sd--; } @@ -2898,211 +3444,185 @@ void pc88_dmac_t::finish(int c) } } -#define STATE_VERSION 5 +#define STATE_VERSION 10 -void PC88::save_state(FILEIO* state_fio) +bool PC88::process_state(FILEIO* state_fio, bool loading) { - state_fio->FputUint32(STATE_VERSION); - state_fio->FputInt32(this_device_id); - - state_fio->Fwrite(ram, sizeof(ram), 1); -#if defined(PC88_EXRAM_BANKS) - state_fio->Fwrite(exram, sizeof(exram), 1); -#endif - state_fio->Fwrite(gvram, sizeof(gvram), 1); - state_fio->Fwrite(tvram, sizeof(tvram), 1); - state_fio->Fwrite(port, sizeof(port), 1); - state_fio->Fwrite(&crtc, sizeof(crtc), 1); - state_fio->Fwrite(&dmac, sizeof(dmac), 1); - state_fio->Fwrite(alu_reg, sizeof(alu_reg), 1); - state_fio->FputUint8(gvram_plane); - state_fio->FputUint8(gvram_sel); - state_fio->FputBool(cpu_clock_low); -#if defined(SUPPORT_PC88_HIGH_CLOCK) - state_fio->FputBool(cpu_clock_high_fe2); -#endif - state_fio->FputBool(mem_wait_on); - state_fio->FputInt32(m1_wait_clocks); - state_fio->FputInt32(f000_m1_wait_clocks); - state_fio->FputInt32(mem_wait_clocks_r); - state_fio->FputInt32(mem_wait_clocks_w); - state_fio->FputInt32(tvram_wait_clocks_r); - state_fio->FputInt32(tvram_wait_clocks_w); - state_fio->FputInt32(gvram_wait_clocks_r); - state_fio->FputInt32(gvram_wait_clocks_w); - state_fio->FputInt32(busreq_clocks); - state_fio->Fwrite(palette, sizeof(palette), 1); - state_fio->FputBool(update_palette); - state_fio->FputBool(hireso); - state_fio->Fwrite(text, sizeof(text), 1); - state_fio->Fwrite(graph, sizeof(graph), 1); - state_fio->Fwrite(palette_text_pc, sizeof(palette_text_pc), 1); - state_fio->Fwrite(palette_graph_pc, sizeof(palette_graph_pc), 1); - state_fio->FputBool(usart_dcd); - state_fio->FputBool(opn_busy); - state_fio->FputUint8(key_caps); - state_fio->FputUint8(key_kana); -#ifdef SUPPORT_PC88_JOYSTICK - state_fio->FputUint32(mouse_strobe_clock); - state_fio->FputUint32(mouse_strobe_clock_lim); - state_fio->FputInt32(mouse_phase); - state_fio->FputInt32(mouse_dx); - state_fio->FputInt32(mouse_dy); - state_fio->FputInt32(mouse_lx); - state_fio->FputInt32(mouse_ly); -#endif - state_fio->FputUint8(intr_req); - state_fio->FputBool(intr_req_sound); -#ifdef SUPPORT_PC88_SB2 - state_fio->FputBool(intr_req_sb2); -#endif - state_fio->FputUint8(intr_mask1); - state_fio->FputUint8(intr_mask2); - state_fio->FputBool(cmt_play); - state_fio->FputBool(cmt_rec); - state_fio->Fwrite(rec_file_path, sizeof(rec_file_path), 1); - if(cmt_rec && cmt_fio->IsOpened()) { - int length_tmp = (int)cmt_fio->Ftell(); - cmt_fio->Fseek(0, FILEIO_SEEK_SET); - state_fio->FputInt32(length_tmp); - while(length_tmp != 0) { - uint8_t buffer[1024]; - int length_rw = min(length_tmp, (int)sizeof(buffer)); - cmt_fio->Fread(buffer, length_rw, 1); - state_fio->Fwrite(buffer, length_rw, 1); - length_tmp -= length_rw; - } - } else { - state_fio->FputInt32(0); - } - state_fio->FputInt32(cmt_bufptr); - state_fio->FputInt32(cmt_bufcnt); - state_fio->Fwrite(cmt_buffer, sizeof(cmt_buffer), 1); - state_fio->Fwrite(cmt_data_carrier, sizeof(cmt_data_carrier), 1); - state_fio->FputInt32(cmt_data_carrier_cnt); - state_fio->FputInt32(cmt_register_id); - state_fio->FputBool(beep_on); - state_fio->FputBool(beep_signal); - state_fio->FputBool(sing_signal); -#ifdef SUPPORT_PC88_PCG8100 - state_fio->FputUint16(pcg_addr); - state_fio->FputUint8(pcg_data); - state_fio->FputUint8(pcg_ctrl); - state_fio->Fwrite(pcg_pattern, sizeof(pcg_pattern), 1); -#endif -#ifdef NIPPY_PATCH - state_fio->FputBool(nippy_patch); -#endif -} - -bool PC88::load_state(FILEIO* state_fio) -{ - release_tape(); - - if(state_fio->FgetUint32() != STATE_VERSION) { + if(!state_fio->StateCheckUint32(STATE_VERSION)) { return false; } - if(state_fio->FgetInt32() != this_device_id) { + if(!state_fio->StateCheckInt32(this_device_id)) { return false; } - state_fio->Fread(ram, sizeof(ram), 1); + state_fio->StateArray(ram, sizeof(ram), 1); #if defined(PC88_EXRAM_BANKS) - state_fio->Fread(exram, sizeof(exram), 1); -#endif - state_fio->Fread(gvram, sizeof(gvram), 1); - state_fio->Fread(tvram, sizeof(tvram), 1); - state_fio->Fread(port, sizeof(port), 1); - state_fio->Fread(&crtc, sizeof(crtc), 1); - state_fio->Fread(&dmac, sizeof(dmac), 1); - state_fio->Fread(alu_reg, sizeof(alu_reg), 1); - gvram_plane = state_fio->FgetUint8(); - gvram_sel = state_fio->FgetUint8(); - cpu_clock_low = state_fio->FgetBool(); + state_fio->StateArray(exram, sizeof(exram), 1); +#endif + state_fio->StateArray(gvram, sizeof(gvram), 1); + state_fio->StateArray(tvram, sizeof(tvram), 1); + state_fio->StateArray(port, sizeof(port), 1); + state_fio->StateValue(crtc.blink.rate); + state_fio->StateValue(crtc.blink.counter); + state_fio->StateValue(crtc.blink.cursor); + state_fio->StateValue(crtc.blink.attrib); + state_fio->StateValue(crtc.cursor.type); + state_fio->StateValue(crtc.cursor.mode); + state_fio->StateValue(crtc.cursor.x); + state_fio->StateValue(crtc.cursor.y); + state_fio->StateValue(crtc.attrib.data); + state_fio->StateValue(crtc.attrib.num); + state_fio->StateArray(&crtc.attrib.expand[0][0], sizeof(crtc.attrib.expand), 1); + state_fio->StateArray(&crtc.text.expand[0][0], sizeof(crtc.text.expand), 1); + state_fio->StateValue(crtc.width); + state_fio->StateValue(crtc.height); + state_fio->StateValue(crtc.char_height); + state_fio->StateValue(crtc.skip_line); + state_fio->StateValue(crtc.vretrace); + state_fio->StateValue(crtc.timing_changed); + state_fio->StateArray(crtc.buffer, sizeof(crtc.buffer), 1); + state_fio->StateValue(crtc.buffer_ptr); + state_fio->StateValue(crtc.cmd); + state_fio->StateValue(crtc.cmd_ptr); + state_fio->StateValue(crtc.mode); + state_fio->StateValue(crtc.reverse); + state_fio->StateValue(crtc.intr_mask); + state_fio->StateValue(crtc.status); + state_fio->StateValue(crtc.vblank); + for(int i = 0; i < array_length(dmac.ch); i++) { + state_fio->StateValue(dmac.ch[i].addr); + state_fio->StateValue(dmac.ch[i].count); + state_fio->StateValue(dmac.ch[i].mode); + state_fio->StateValue(dmac.ch[i].nbytes); + state_fio->StateValue(dmac.ch[i].running); + } + state_fio->StateValue(dmac.mode); + state_fio->StateValue(dmac.status); + state_fio->StateValue(dmac.high_low); + state_fio->StateArray(alu_reg, sizeof(alu_reg), 1); + state_fio->StateValue(gvram_plane); + state_fio->StateValue(gvram_sel); + state_fio->StateValue(cpu_clock_low); #if defined(SUPPORT_PC88_HIGH_CLOCK) - cpu_clock_high_fe2 = state_fio->FgetBool(); -#endif - mem_wait_on = state_fio->FgetBool(); - m1_wait_clocks = state_fio->FgetInt32(); - f000_m1_wait_clocks = state_fio->FgetInt32(); - mem_wait_clocks_r = state_fio->FgetInt32(); - mem_wait_clocks_w = state_fio->FgetInt32(); - tvram_wait_clocks_r = state_fio->FgetInt32(); - tvram_wait_clocks_w = state_fio->FgetInt32(); - gvram_wait_clocks_r = state_fio->FgetInt32(); - gvram_wait_clocks_w = state_fio->FgetInt32(); - busreq_clocks = state_fio->FgetInt32(); - state_fio->Fread(palette, sizeof(palette), 1); - update_palette = state_fio->FgetBool(); - hireso = state_fio->FgetBool(); - state_fio->Fread(text, sizeof(text), 1); - state_fio->Fread(graph, sizeof(graph), 1); - state_fio->Fread(palette_text_pc, sizeof(palette_text_pc), 1); - state_fio->Fread(palette_graph_pc, sizeof(palette_graph_pc), 1); - usart_dcd = state_fio->FgetBool(); - opn_busy = state_fio->FgetBool(); - key_caps = state_fio->FgetUint8(); - key_kana = state_fio->FgetUint8(); + state_fio->StateValue(cpu_clock_high_fe2); +#endif + state_fio->StateValue(mem_wait_on); + state_fio->StateValue(m1_wait_clocks); + state_fio->StateValue(f000_m1_wait_clocks); + state_fio->StateValue(mem_wait_clocks_r); + state_fio->StateValue(mem_wait_clocks_w); + state_fio->StateValue(tvram_wait_clocks_r); + state_fio->StateValue(tvram_wait_clocks_w); + state_fio->StateValue(gvram_wait_clocks_r); + state_fio->StateValue(gvram_wait_clocks_w); + state_fio->StateValue(busreq_clocks); + for(int i = 0; i < array_length(palette); i++) { + state_fio->StateValue(palette[i].r); + state_fio->StateValue(palette[i].g); + state_fio->StateValue(palette[i].b); + } +// state_fio->StateValue(update_palette); + state_fio->StateValue(hireso); + state_fio->StateArray(&text[0][0], sizeof(text), 1); + state_fio->StateArray(&graph[0][0], sizeof(graph), 1); +/* + for(int i = 0; i < 9; i++) { + state_fio->StateValue(palette_digital[i].b); + state_fio->StateValue(palette_digital[i].r); + state_fio->StateValue(palette_digital[i].g); + state_fio->StateValue(palette_analog [i].b); + state_fio->StateValue(palette_analog [i].r); + state_fio->StateValue(palette_analog [i].g); + } +*/ + state_fio->StateValue(usart_dcd); + state_fio->StateValue(opn_busy); + state_fio->StateValue(key_caps); + state_fio->StateValue(key_kana); #ifdef SUPPORT_PC88_JOYSTICK - mouse_strobe_clock = state_fio->FgetUint32(); - mouse_strobe_clock_lim = state_fio->FgetUint32(); - mouse_phase = state_fio->FgetInt32(); - mouse_dx = state_fio->FgetInt32(); - mouse_dy = state_fio->FgetInt32(); - mouse_lx = state_fio->FgetInt32(); - mouse_ly = state_fio->FgetInt32(); -#endif - intr_req = state_fio->FgetUint8(); - intr_req_sound = state_fio->FgetBool(); + state_fio->StateValue(mouse_strobe_clock); + state_fio->StateValue(mouse_strobe_clock_lim); + state_fio->StateValue(mouse_phase); + state_fio->StateValue(mouse_dx); + state_fio->StateValue(mouse_dy); + state_fio->StateValue(mouse_lx); + state_fio->StateValue(mouse_ly); +#endif + state_fio->StateValue(intr_req); + state_fio->StateValue(intr_req_sound); #ifdef SUPPORT_PC88_SB2 - intr_req_sb2 = state_fio->FgetBool(); -#endif - intr_mask1 = state_fio->FgetUint8(); - intr_mask2 = state_fio->FgetUint8(); - cmt_play = state_fio->FgetBool(); - cmt_rec = state_fio->FgetBool(); - state_fio->Fread(rec_file_path, sizeof(rec_file_path), 1); - int length_tmp = state_fio->FgetInt32(); - if(cmt_rec) { - cmt_fio->Fopen(rec_file_path, FILEIO_READ_WRITE_NEW_BINARY); - while(length_tmp != 0) { - uint8_t buffer[1024]; - int length_rw = min(length_tmp, (int)sizeof(buffer)); - state_fio->Fread(buffer, length_rw, 1); - if(cmt_fio->IsOpened()) { - cmt_fio->Fwrite(buffer, length_rw, 1); - } - length_tmp -= length_rw; - } - } - cmt_bufptr = state_fio->FgetInt32(); - cmt_bufcnt = state_fio->FgetInt32(); - state_fio->Fread(cmt_buffer, sizeof(cmt_buffer), 1); - state_fio->Fread(cmt_data_carrier, sizeof(cmt_data_carrier), 1); - cmt_data_carrier_cnt = state_fio->FgetInt32(); - cmt_register_id = state_fio->FgetInt32(); - beep_on = state_fio->FgetBool(); - beep_signal = state_fio->FgetBool(); - sing_signal = state_fio->FgetBool(); + state_fio->StateValue(intr_req_sb2); +#endif + state_fio->StateValue(intr_mask1); + state_fio->StateValue(intr_mask2); + state_fio->StateValue(cmt_play); + state_fio->StateValue(cmt_rec); + state_fio->StateArray(rec_file_path, sizeof(rec_file_path), 1); + if(loading) { + int length_tmp = state_fio->FgetInt32_LE(); + if(cmt_rec) { + cmt_fio->Fopen(rec_file_path, FILEIO_READ_WRITE_NEW_BINARY); + while(length_tmp != 0) { + uint8_t buffer[1024]; + int length_rw = min(length_tmp, (int)sizeof(buffer)); + state_fio->Fread(buffer, length_rw, 1); + if(cmt_fio->IsOpened()) { + cmt_fio->Fwrite(buffer, length_rw, 1); + } + length_tmp -= length_rw; + } + } + } else { + if(cmt_rec && cmt_fio->IsOpened()) { + int length_tmp = (int)cmt_fio->Ftell(); + cmt_fio->Fseek(0, FILEIO_SEEK_SET); + state_fio->FputInt32_LE(length_tmp); + while(length_tmp != 0) { + uint8_t buffer[1024]; + int length_rw = min(length_tmp, (int)sizeof(buffer)); + cmt_fio->Fread(buffer, length_rw, 1); + state_fio->Fwrite(buffer, length_rw, 1); + length_tmp -= length_rw; + } + } else { + state_fio->FputInt32_LE(0); + } + } + state_fio->StateValue(cmt_bufptr); + state_fio->StateValue(cmt_bufcnt); + state_fio->StateArray(cmt_buffer, sizeof(cmt_buffer), 1); + state_fio->StateArray(cmt_data_carrier, sizeof(cmt_data_carrier), 1); + state_fio->StateValue(cmt_data_carrier_cnt); + state_fio->StateValue(cmt_register_id); + state_fio->StateValue(beep_on); + state_fio->StateValue(beep_signal); + state_fio->StateValue(sing_signal); #ifdef SUPPORT_PC88_PCG8100 - pcg_addr = state_fio->FgetUint16(); - pcg_data = state_fio->FgetUint8(); - pcg_ctrl = state_fio->FgetUint8(); - state_fio->Fread(pcg_pattern, sizeof(pcg_pattern), 1); + state_fio->StateValue(pcg_addr); + state_fio->StateValue(pcg_data); + state_fio->StateValue(pcg_ctrl); + state_fio->StateArray(pcg_pattern, sizeof(pcg_pattern), 1); +#endif +#ifdef SUPPORT_PC88_CDROM + state_fio->StateValue(cdda_register_id); + state_fio->StateValue(cdda_volume); #endif #ifdef NIPPY_PATCH - nippy_patch = state_fio->FgetBool(); + state_fio->StateValue(nippy_patch); #endif // post process - dmac.mem = dmac.ch[2].io = this; - dmac.ch[0].io = dmac.ch[1].io = dmac.ch[3].io = vm->dummy; + if(loading) { #if defined(_PC8001SR) - update_n80_write(); - update_n80_read(); + update_n80_write(); + update_n80_read(); #else - update_low_memmap(); - update_tvram_memmap(); + update_low_memmap(); + update_tvram_memmap(); #endif + // force update palette when state file is loaded + update_palette = true; + } return true; } - +} +