diff --git a/src/ibm.h b/src/ibm.h index 5d3ac3b..62f8035 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -281,6 +281,7 @@ enum GFX_EGA, /*Using IBM EGA BIOS*/ GFX_TVGA, /*Using Trident TVGA8900D BIOS*/ GFX_ET4000, /*Tseng ET4000*/ + GFX_KASAN16VGA, /*Kasan Hangulmadang-16 (Tseng ET4000AX)*/ GFX_TGKOREANVGA, /*Trigem Korean VGA(Tseng ET4000AX)*/ GFX_ET4000W32, /*Tseng ET4000/W32p (Diamond Stealth 32)*/ GFX_BAHAMAS64, /*S3 Vision864 (Paradise Bahamas 64)*/ diff --git a/src/vid_ati28800.c b/src/vid_ati28800.c index 1d024f4..871f1c5 100644 --- a/src/vid_ati28800.c +++ b/src/vid_ati28800.c @@ -368,6 +368,10 @@ void *ati28800k_init() ati28800->svga.miscout = 1; ati28800->svga.ksc5601_sbyte_mask = 0; + ati28800->svga.ksc5601_udc_area_msb[0] = 0xC9; + ati28800->svga.ksc5601_udc_area_msb[1] = 0xFE; + ati28800->svga.ksc5601_swap_mode = 0; + ati28800->svga.ksc5601_english_font_type = 0; ati_eeprom_load(&ati28800->eeprom, "atikorvga.nvr", 0); @@ -401,6 +405,10 @@ void *ati28800k_spc4620p_init() ati28800->svga.miscout = 1; ati28800->svga.ksc5601_sbyte_mask = 0; + ati28800->svga.ksc5601_udc_area_msb[0] = 0xC9; + ati28800->svga.ksc5601_udc_area_msb[1] = 0xFE; + ati28800->svga.ksc5601_swap_mode = 0; + ati28800->svga.ksc5601_english_font_type = 0; ati_eeprom_load(&ati28800->eeprom, "svb6120a.nvr", 0); @@ -434,7 +442,10 @@ void *ati28800k_spc6033p_init() ati28800->svga.miscout = 1; ati28800->svga.ksc5601_sbyte_mask = 0; - + ati28800->svga.ksc5601_udc_area_msb[0] = 0xC9; + ati28800->svga.ksc5601_udc_area_msb[1] = 0xFE; + ati28800->svga.ksc5601_swap_mode = 0; + ati28800->svga.ksc5601_english_font_type = 0; ati_eeprom_load(&ati28800->eeprom, "svb6120a_spc6033p.nvr", 0); diff --git a/src/vid_et4000.c b/src/vid_et4000.c index 161e741..25cb60d 100644 --- a/src/vid_et4000.c +++ b/src/vid_et4000.c @@ -25,6 +25,11 @@ typedef struct et4000_t int get_korean_font_enabled; int get_korean_font_index; uint16_t get_korean_font_base; + + uint8_t kasan_cfg_index; + uint8_t kasan_cfg_regs[16]; + uint16_t kasan_access_addr; + uint8_t kasan_font_data[4]; } et4000_t; static uint8_t crtc_mask[0x40] = @@ -39,6 +44,9 @@ static uint8_t crtc_mask[0x40] = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +void et4000_kasan_out(uint16_t addr, uint8_t val, void *p); +uint8_t et4000_kasan_in(uint16_t addr, void *p); + void et4000_out(uint16_t addr, uint8_t val, void *p) { et4000_t *et4000 = (et4000_t *)p; @@ -137,6 +145,118 @@ void et4000k_out(uint16_t addr, uint8_t val, void *p) et4000->port_32cb_val = val; svga_recalctimings(&et4000->svga); break; + default: + et4000_out(addr, val, p); + break; + } +} + +void et4000_kasan_out(uint16_t addr, uint8_t val, void *p) +{ + et4000_t *et4000 = (et4000_t *)p; + +// pclog("ET4000k out %04X %02X\n", addr, val); + + + if(addr == 0x258) + { + //pclog("Write port %04X to %02X at %04X:%04X\n", addr, val, CS, cpu_state.oldpc); + et4000->kasan_cfg_index = val; + } + else if(addr == 0x259) + { + //pclog("Write port %04X to %02X at %04X:%04X\n", addr, val, CS, cpu_state.oldpc); + if(et4000->kasan_cfg_index >= 0xF0) + { + switch(et4000->kasan_cfg_index - 0xF0) + { + case 0: + if(et4000->kasan_cfg_regs[4] & 8) + val = (val & 0xFC) | (et4000->kasan_cfg_regs[0] & 3); + et4000->kasan_cfg_regs[0] = val; + svga_recalctimings(&et4000->svga); + break; + case 1: + case 2: + et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val; + io_removehandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); + et4000->kasan_access_addr = (et4000->kasan_cfg_regs[2] << 8) | et4000->kasan_cfg_regs[1]; + io_sethandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); + //pclog("Set font access address to %04X\n", et4000->kasan_access_addr); + break; + case 4: + if(et4000->kasan_cfg_regs[0] & 0x20) + val |= 0x80; + et4000->svga.ksc5601_swap_mode = (val & 4) >> 2; + et4000->kasan_cfg_regs[4] = val; + svga_recalctimings(&et4000->svga); + break; + case 5: + et4000->kasan_cfg_regs[5] = val; + et4000->svga.ksc5601_english_font_type = 0x100 | val; + case 6: + case 7: + et4000->svga.ksc5601_udc_area_msb[et4000->kasan_cfg_index - 0xF6] = val; + default: + et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val; + svga_recalctimings(&et4000->svga); + break; + } + } + } + else if(addr >= et4000->kasan_access_addr && addr < et4000->kasan_access_addr + 8) + { + switch (addr - ((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1]))) + { + case 0: + if(et4000->kasan_cfg_regs[0] & 2) + { + et4000->get_korean_font_index = ((val & 1) << 4) | ((val & 0x1E) >> 1); + et4000->get_korean_font_base = (et4000->get_korean_font_base & ~7) | (val >> 5); + } + break; + case 1: + if(et4000->kasan_cfg_regs[0] & 2) + { + et4000->get_korean_font_base = (et4000->get_korean_font_base & ~0x7F8) | (val << 3); + } + break; + case 2: + if(et4000->kasan_cfg_regs[0] & 2) + { + et4000->get_korean_font_base = (et4000->get_korean_font_base & ~0x7F800) | ((val & 7) << 11); + } + break; + case 3: + case 4: + case 5: + if(et4000->kasan_cfg_regs[0] & 1) + { + et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val; + } + break; + case 6: + if((et4000->kasan_cfg_regs[0] & 1) && (et4000->kasan_font_data[3] & !val & 0x80) && (et4000->get_korean_font_base & 0x7F) >= 0x20 && (et4000->get_korean_font_base & 0x7F) < 0x7F) + { + if(((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[0] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[0] & 0x80)) + { + fontdatksc5601_user[(et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index] = et4000->kasan_font_data[2]; + } + else if(((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[1] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[1] & 0x80)) + { + fontdatksc5601_user[96 + (et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index] = et4000->kasan_font_data[2]; + } + } + et4000->kasan_font_data[3] = val; + break; + default: + break; + } + //pclog("Write port %04X at %04X:%04X\n", addr, CS, cpu_state.oldpc); + } + else + { + et4000_out(addr, val, p); } } @@ -220,7 +340,60 @@ uint8_t et4000k_in(uint16_t addr, void *p) return et4000->port_32cb_val; } - return 0xff; + return et4000_in(addr, p); +} + +uint8_t et4000_kasan_in(uint16_t addr, void *p) +{ + uint8_t val = 0xFF; + et4000_t *et4000 = (et4000_t *)p; + + if(addr == 0x258) + { + //pclog("Read port %04X at %04X:%04X\n", addr, CS, cpu_state.oldpc); + val = et4000->kasan_cfg_index; + } + else if(addr == 0x259) + { + //pclog("Read port %04X at %04X:%04X\n", addr, CS, cpu_state.oldpc); + if (et4000->kasan_cfg_index >= 0xF0) + { + val = et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0]; + if(et4000->kasan_cfg_index == 0xF4 && et4000->kasan_cfg_regs[0] & 0x20) + val |= 0x80; + } + } + else if(addr >= et4000->kasan_access_addr && addr < et4000->kasan_access_addr + 8) + { + switch (addr - ((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1]))) + { + case 2: + val = 0; + break; + case 5: + if(((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[0] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[0] & 0x80)) + { + val = fontdatksc5601_user[(et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index]; + } + else if(((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[1] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[1] & 0x80)) + { + val = fontdatksc5601_user[96 + (et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index]; + } + else + { + val = fontdatksc5601[et4000->get_korean_font_base][et4000->get_korean_font_index]; + } + break; + default: + break; + } + //pclog(stderr, "Read port %04X at %04X:%04X\n", addr, CS, cpu_state.oldpc); + } + else + { + val = et4000_in(addr, p); + } + return val; } void et4000_recalctimings(svga_t *svga) @@ -276,6 +449,22 @@ void et4000k_recalctimings(svga_t *svga) } } +void et4000_kasan_recalctimings(svga_t *svga) +{ + et4000_t *et4000 = (et4000_t *)svga->p; + + et4000_recalctimings(svga); + + if (svga->render == svga_render_text_80 && (et4000->kasan_cfg_regs[0] & 8)) + { + svga->ma_latch -= 3; + svga->ca_adj = (et4000->kasan_cfg_regs[0] >> 6) - 3; + svga->ksc5601_sbyte_mask = (et4000->kasan_cfg_regs[0] & 4) << 5; + if((et4000->kasan_cfg_regs[0] & 0x23) == 0x20 && (et4000->kasan_cfg_regs[4] & 0x80) && ((svga->crtc[0x37] & 0x0B) == 0x0A)) + svga->render = svga_render_text_80_ksc5601; + } +} + void *et4000_init() { et4000_t *et4000 = malloc(sizeof(et4000_t)); @@ -317,6 +506,54 @@ void *et4000k_init() NULL); et4000->svga.ksc5601_sbyte_mask = 0x80; + et4000->svga.ksc5601_udc_area_msb[0] = 0xC9; + et4000->svga.ksc5601_udc_area_msb[1] = 0xFE; + et4000->svga.ksc5601_swap_mode = 0; + et4000->svga.ksc5601_english_font_type = 0; + + return et4000; +} + +void *et4000_kasan_init() +{ + int i; + et4000_t *et4000 = malloc(sizeof(et4000_t)); + memset(et4000, 0, sizeof(et4000_t)); + + rom_init(&et4000->bios_rom, "et4000_kasan16.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + loadfont("kasan_ksc5601.rom", 6); + + io_sethandler(0x03c0, 0x0020, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000); + + io_sethandler(0x0258, 0x0002, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); + + svga_init(&et4000->svga, et4000, 1 << 20, /*1mb*/ + et4000_kasan_recalctimings, + et4000_in, et4000_out, + NULL, + NULL); + + et4000->svga.ksc5601_sbyte_mask = 0; + et4000->kasan_cfg_index = 0; + for(i=0; i<16; i++) + et4000->kasan_cfg_regs[i] = 0; + for(i=0; i<4; i++) + et4000->kasan_font_data[i] = 0; + et4000->kasan_cfg_regs[1] = 0x50; + et4000->kasan_cfg_regs[2] = 2; + et4000->kasan_cfg_regs[3] = 6; + et4000->kasan_cfg_regs[4] = 0x78; + et4000->kasan_cfg_regs[5] = 0xFF; + et4000->kasan_cfg_regs[6] = 0xC9; + et4000->kasan_cfg_regs[7] = 0xFE; + et4000->kasan_access_addr = 0x250; + io_sethandler(0x250, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000); + + et4000->svga.ksc5601_sbyte_mask = 0; + et4000->svga.ksc5601_udc_area_msb[0] = 0xC9; + et4000->svga.ksc5601_udc_area_msb[1] = 0xFE; + et4000->svga.ksc5601_swap_mode = 0; + et4000->svga.ksc5601_english_font_type = 0x1FF; return et4000; } @@ -331,6 +568,11 @@ static int et4000k_available() return rom_present("tgkorvga.bin") && rom_present("tg_ksc5601.rom");; } +static int et4000_kasan_available() +{ + return rom_present("et4000_kasan16.bin") && rom_present("kasan_ksc5601.rom");; +} + void et4000_close(void *p) { et4000_t *et4000 = (et4000_t *)p; @@ -384,3 +626,15 @@ device_t et4000k_device = et4000_force_redraw, et4000_add_status_info }; + +device_t et4000_kasan_device = +{ + "Kasan Hangulmadang-16(Tseng Labs ET4000AX)", + 0, + et4000_kasan_init, + et4000_close, + et4000_kasan_available, + et4000_speed_changed, + et4000_force_redraw, + et4000_add_status_info +}; diff --git a/src/vid_et4000.h b/src/vid_et4000.h index b5b0170..9d18590 100644 --- a/src/vid_et4000.h +++ b/src/vid_et4000.h @@ -1,2 +1,3 @@ extern device_t et4000_device; extern device_t et4000k_device; +extern device_t et4000_kasan_device; diff --git a/src/vid_svga.c b/src/vid_svga.c index cb65e29..7b0098e 100644 --- a/src/vid_svga.c +++ b/src/vid_svga.c @@ -774,6 +774,7 @@ int svga_init(svga_t *svga, void *p, int memsize, svga->hwcursor_draw = hwcursor_draw; svga->overlay_draw = overlay_draw; svga->hwcursor.ysize = 64; + svga->ksc5601_english_font_type = 0; // _svga_recalctimings(svga); mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, MEM_MAPPING_EXTERNAL, svga); diff --git a/src/vid_svga.h b/src/vid_svga.h index 1f99150..3a0668b 100644 --- a/src/vid_svga.h +++ b/src/vid_svga.h @@ -138,7 +138,10 @@ typedef struct svga_t void *p; uint8_t ksc5601_sbyte_mask; - + uint8_t ksc5601_udc_area_msb[2]; + int ksc5601_swap_mode; + uint16_t ksc5601_english_font_type; + int vertical_linedbl; /*Used to implement CRTC[0x17] bit 2 hsync divisor*/ diff --git a/src/vid_svga_render.c b/src/vid_svga_render.c index 92d177c..680772d 100644 --- a/src/vid_svga_render.c +++ b/src/vid_svga_render.c @@ -203,10 +203,17 @@ void svga_render_text_80_ksc5601(svga_t *svga) if(x + xinc < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) { - if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff)) - dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc]; + if((chr == svga->ksc5601_udc_area_msb[0] || chr == svga->ksc5601_udc_area_msb[1]) && (nextchr > 0xa0 && nextchr < 0xff)) + dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc]; else if(nextchr & 0x80) + { + if(svga->ksc5601_swap_mode == 1 && (nextchr > 0xa0 && nextchr < 0xff)) + { + if(chr >= 0x80 && chr < 0x99) chr += 0x30; + else if(chr >= 0xB0 && chr < 0xC9) chr -= 0x30; + } dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)][svga->sc]; + } else dat = 0xFF; } @@ -215,7 +222,8 @@ void svga_render_text_80_ksc5601(svga_t *svga) if (attr & 8) charaddr = svga->charsetb + (chr * 128); else charaddr = svga->charseta + (chr * 128); - dat = svga->vram[charaddr + (svga->sc << 2)]; + if ((svga->ksc5601_english_font_type >> 8) == 1) dat = fontdatksc5601[((svga->ksc5601_english_font_type & 0x7F) << 7) | (chr >> 1)][((chr & 1) << 4) | svga->sc]; + else dat = svga->vram[charaddr + (svga->sc << 2)]; } if (svga->seqregs[1] & 1) { @@ -255,10 +263,12 @@ void svga_render_text_80_ksc5601(svga_t *svga) } } - if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff)) - dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc + 16]; + if((chr == svga->ksc5601_udc_area_msb[0] || chr == svga->ksc5601_udc_area_msb[1]) && (nextchr > 0xa0 && nextchr < 0xff)) + dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc + 16]; else if(nextchr & 0x80) + { dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)][svga->sc + 16]; + } else dat = 0xFF; if (svga->seqregs[1] & 1) diff --git a/src/video.c b/src/video.c index fd78a5c..2c81093 100644 --- a/src/video.c +++ b/src/video.c @@ -102,6 +102,7 @@ static VIDEO_CARD video_cards[] = {"Hercules InColor", "incolor", &incolor_device, GFX_INCOLOR, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, {"IBM 1MB SVGA Adapter/A (CL GD5428)", "ibm1mbsvga", &ibm_gd5428_device, GFX_IBM_GD5428, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, {"Image Manager 1024", "im1024", &im1024_device, GFX_IM1024, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, + {"Kasan Hangulmadang-16 (Tseng ET4000AX)", "kasan16", &et4000_kasan_device, GFX_KASAN16VGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, {"Matrox Mystique", "mystique", &mystique_device, GFX_MYSTIQUE, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}}, {"MDA", "mda", &mda_device, GFX_MDA, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, {"MDSI Genius", "genius", &genius_device, GFX_GENIUS, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},