From 47251459736d4a9b7696ee4a89b4a4bd7a3b9122 Mon Sep 17 00:00:00 2001 From: Melissa Goad Date: Sun, 25 Feb 2018 18:49:29 -0600 Subject: [PATCH 1/9] Many RIVA 128 fixes --- src/video/vid_nv_riva128.c | 228 +++++++++++++++++++++++++------------ 1 file changed, 156 insertions(+), 72 deletions(-) diff --git a/src/video/vid_nv_riva128.c b/src/video/vid_nv_riva128.c index afaf8e878..2dbe47a3c 100644 --- a/src/video/vid_nv_riva128.c +++ b/src/video/vid_nv_riva128.c @@ -207,6 +207,8 @@ typedef struct riva128_t uint32_t dma_intr, dma_intr_en; + uint32_t status; + struct { uint32_t point_color; @@ -238,14 +240,17 @@ typedef struct riva128_t { int scl; int sda; - int busy; + enum + { + I2C_START, I2C_STOP, I2C_WAITACK, I2C_READ, I2C_WRITE + } state; unsigned addrbits; unsigned databits; uint8_t addr; //actually 7 bits uint8_t data; struct { - uint8_t addr; + uint8_t addr; //actually 7 bits uint8_t edid_rom[128]; } edid_rom; } i2c; @@ -1267,6 +1272,21 @@ void rivatnt_pgraph_ctx_switch(void *p) ret = riva128->pgraph.fifo_enable & 1; break; + case 0x4006b0: + ret = riva128->pgraph.status & 0xff; + break; + case 0x4006b1: + ret = (riva128->pgraph.status >> 8) & 0xff; + break; + case 0x4006b2: + ret = (riva128->pgraph.status >> 16) & 0xff; + break; + case 0x4006b3: + ret = (riva128->pgraph.status >> 24) & 0xff; + //HACK + riva128->pgraph.status ^= 0x1f131111; + break; + case 0x401100: ret = riva128->pgraph.dma_intr & 0xff; break; @@ -1808,14 +1828,13 @@ void riva128_pgraph_vblank_interrupt(void *p) { riva128_t *riva128 = (riva128_t *)p; uint32_t ramht_base = riva128->pfifo.ramht_addr; + uint32_t ret = 0; uint32_t tmp = handle; uint32_t hash = 0; int bits; - pclog("RIVA 128 RAMHT lookup with handle %08X %04X:%08X\n", handle, CS, cpu_state.pc); - switch(riva128->pfifo.ramht_size) { case 4096: @@ -1828,21 +1847,25 @@ void riva128_pgraph_vblank_interrupt(void *p) bits = 15; } - while(handle) + while(tmp) { hash ^= (tmp & (riva128->pfifo.ramht_size - 1)); - tmp = handle >> 1; + tmp = tmp >> 1; } hash ^= riva128->pfifo.caches[1].chanid << (bits - 4); - return riva128->pramin[ramht_base + (hash * 8)]; + ret = riva128->pramin[ramht_base + (hash * 8)]; + + pclog("RIVA 128 RAMHT lookup with handle %08X returned %08X %04X:%08X\n", handle, ret, CS, cpu_state.pc); + + return ret; } void riva128_puller_exec_method(int chanid, int subchanid, int offset, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; - pclog("RIVA 128 Puller executing method %04X on channel %01X[%01X] %04X:%08X\n", offset, chanid, subchanid, val, CS, cpu_state.pc); + pclog("RIVA 128 Puller executing method %04X on channel %01X[%01X] param %08X %04X:%08X\n", offset, chanid, subchanid, val, CS, cpu_state.pc); if(riva128->card_id == 0x03) { @@ -1927,6 +1950,36 @@ void riva128_pgraph_vblank_interrupt(void *p) } } +uint8_t riva128_user_read(uint32_t addr, void *p) +{ + riva128_t *riva128 = (riva128_t *)p; + int chanid = (addr >> 16) & 0xf; + int subchanid = (addr >> 13) & 0x7; + int offset = addr & 0x1fff; + uint8_t ret = 0; + + pclog("RIVA 128 USER read %08X %04X:%08X\n", addr, CS, cpu_state.pc); + + addr -= 0x800000; + + if(riva128->pfifo.chan_mode & (1 << chanid)) + { + //DMA mode reads??? + } + else + { + //PIO mode + switch(offset) + { + //HACK + case 0x10: ret = 0xff; break; + case 0x11: ret = 0x7f; break; + } + } + + return ret; +} + void riva128_user_write(uint32_t addr, uint32_t val, void *p) { riva128_t *riva128 = (riva128_t *)p; @@ -1954,8 +2007,23 @@ void riva128_pgraph_vblank_interrupt(void *p) } else { + uint32_t err = -1; + int intr = 1; //PIO mode - riva128_puller_exec_method(chanid, subchanid, offset, val, riva128); + //if((offset & 0x1f00) && (offset != 0)) err = 5; //Reserved access + //if((offset & 0x1ff0) == 0x0020) intr = 0; + //if(!riva128->pfifo.caches[1].push_enabled) err = 1; //Pusher disabled + //else + { + riva128_puller_exec_method(chanid, subchanid, offset, val, riva128); + riva128->pgraph.status = 0x1f131111; //HACK + } + if(err != -1) + { + uint32_t w = (addr & 0x7fffff) | (err << 28); + if(intr) riva128_pfifo_interrupt(4, riva128); + + } } } @@ -1981,6 +2049,7 @@ void riva128_pgraph_vblank_interrupt(void *p) if((addr >= 0x300000) && (addr <= 0x30ffff) && (riva128->card_id >= 0x04)) ret = riva128->bios_rom.rom[addr & riva128->bios_rom.mask]; if((addr >= 0x400000) && (addr <= 0x400fff)) ret = riva128_pgraph_read(addr, riva128); if((addr >= 0x680000) && (addr <= 0x680fff)) ret = riva128_pramdac_read(addr, riva128); + if(addr >= 0x800000) ret = riva128_user_read(addr, riva128); switch(addr) { @@ -2246,34 +2315,47 @@ void riva128_ptimer_tick(void *p) case 0x3D5: switch(svga->crtcreg) { - case 0x3e: - if(riva128->i2c.busy == 2) - { - if(riva128->i2c.addr == 0xA1) - { - //pclog("RIVA 128 Read EDID %02x %02x\n", riva128->i2c.edid_rom.addr, riva128->i2c.edid_rom.edid_rom[riva128->i2c.edid_rom.addr]); - riva128->i2c.data <<= 1; - riva128->i2c.data |= (riva128->i2c.edid_rom.edid_rom[riva128->i2c.edid_rom.addr] & (1 << riva128->i2c.databits)) >> riva128->i2c.databits; - } - riva128->i2c.databits++; - if(riva128->i2c.databits == 8) - { - riva128->i2c.databits = 0; - riva128->i2c.edid_rom.addr++; - riva128->i2c.busy = 0; - } - } - ret = (riva128->i2c.sda << 3) | (riva128->i2c.scl << 2); - break; case 0x28: ret = svga->crtc[0x28] & 0x3f; break; + case 0x34: + ret = svga->displine & 0xff; + break; + case 0x35: + ret = (svga->displine >> 8) & 7; + break; + case 0x3e: + //DDC status register + ret = (riva128->i2c.sda << 3) | (riva128->i2c.scl << 2); + if(riva128->i2c.state == I2C_READ) + { + if(riva128->i2c.scl) + { + if(riva128->i2c.databits > 8) + { + riva128->i2c.data <<= 1; + if(riva128->i2c.addr == 0xA1) + { + riva128->i2c.data |= (riva128->i2c.edid_rom.edid_rom[riva128->i2c.edid_rom.addr] & (0x80 >> riva128->i2c.databits)) >> riva128->i2c.databits; + } + else riva128->i2c.data = 0; + riva128->i2c.databits++; + } + if(riva128->i2c.databits == 8) + { + riva128->i2c.state = I2C_WAITACK; + riva128->i2c.sda = 0; + riva128->i2c.edid_rom.addr++; + } + } + } + break; default: ret = svga->crtc[svga->crtcreg]; break; } - //if(svga->crtcreg > 0x18) - // pclog("RIVA 128 Extended CRTC read %02X %04X:%08X\n", svga->crtcreg, CS, cpu_state.pc); + if(svga->crtcreg > 0x18) + pclog("RIVA 128 Extended CRTC read %02X %04X:%08X\n", svga->crtcreg, CS, cpu_state.pc); break; default: ret = svga_in(addr, svga); @@ -2343,44 +2425,46 @@ void riva128_ptimer_tick(void *p) riva128->rma.mode = val & 0xf; break; case 0x3f: - if((val & 0x20) && (riva128->i2c.sda == 0) && (val & 0x10)) + //FULL EMULATION OF I2C AND DDC PROTOCOLS INCOMING + if(riva128->i2c.sda && riva128->i2c.scl && ((val & 0x30) == 0)) { - //I2C Start Condition. - riva128->i2c.busy = 1; + riva128->i2c.state = I2C_START; + riva128->i2c.addr = 0; + riva128->i2c.addrbits = 0; + riva128->i2c.data = 0; + riva128->i2c.databits = 0; } - if((val & 0x20) && (riva128->i2c.sda == 1) && !(val & 0x10)) + else if(!riva128->i2c.sda && !riva128->i2c.scl && ((val & 0x30) == 0x30)) riva128->i2c.state = I2C_STOP; + else if(riva128->i2c.state == I2C_START) { - //I2C Stop Condition. - riva128->i2c.busy = 0; - } - riva128->i2c.scl = (val & 0x20) ? 1 : 0; - riva128->i2c.sda = (val & 0x10) ? 1 : 0; - if(riva128->i2c.busy == 1) - { - riva128->i2c.addr <<= 1; - riva128->i2c.addr |= riva128->i2c.sda; - riva128->i2c.addrbits++; - if(riva128->i2c.addrbits == 8) + if(val & 0x20) { - riva128->i2c.busy = 2; - riva128->i2c.addrbits = 0; - } - } - if(riva128->i2c.busy == 2) - { - riva128->i2c.data <<= 1; - riva128->i2c.addr |= riva128->i2c.sda; - riva128->i2c.databits++; - if(riva128->i2c.databits == 8) - { - if(riva128->i2c.addr == 0xA0) + if(riva128->i2c.addrbits > 8) { - //pclog("RIVA 128 Write EDID Address %02x\n", riva128->i2c.data); - riva128->i2c.edid_rom.addr = riva128->i2c.data; + riva128->i2c.addr <<= 1; + riva128->i2c.addr |= (val >> 4) & 1; + riva128->i2c.addrbits++; + } + if(riva128->i2c.addrbits == 8) + { + riva128->i2c.state = I2C_WAITACK; + riva128->i2c.sda = 0; + if(riva128->i2c.addr == 0xA1) riva128->i2c.edid_rom.addr = 0; } - riva128->i2c.databits = 0; } } + else if(riva128->i2c.state == I2C_WAITACK) + { + if(riva128->i2c.edid_rom.addr == 0x80) + { + riva128->i2c.edid_rom.addr = 0; + riva128->i2c.state = I2C_STOP; + } + else riva128->i2c.state = I2C_READ; + } + + riva128->i2c.sda = (val >> 4) & 1; + riva128->i2c.scl = (val >> 5) & 1; break; } //if(svga->crtcreg > 0x18) @@ -2979,7 +3063,7 @@ void *riva128_init(device_t *info) riva128->i2c.addrbits = 0; riva128->i2c.databits = 0; - riva128->i2c.busy = 0; + riva128->i2c.state = I2C_STOP; uint8_t edid_rom[128] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -3010,7 +3094,7 @@ void *riva128_init(device_t *info) riva128->nvenable = 1; timer_add(riva128_mclk_poll, &riva128->mtime, &timer_one, riva128); - timer_add(riva128_nvclk_poll, &riva128->nvtime, &riva128->nvenable, riva128); + timer_add(riva128_nvclk_poll, &riva128->nvtime, &timer_one, riva128); riva128->svga.vblank_start = riva128_vblank_start; @@ -3214,7 +3298,7 @@ void *rivatnt_init(device_t *info) riva128->i2c.addrbits = 0; riva128->i2c.databits = 0; - riva128->i2c.busy = 0; + riva128->i2c.state = I2C_STOP; uint8_t edid_rom[128] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -3241,11 +3325,11 @@ void *rivatnt_init(device_t *info) } } - riva128->menable = 0; - riva128->nvenable = 0; + riva128->menable = 1; + riva128->nvenable = 1; - timer_add(riva128_mclk_poll, &riva128->mtime, &riva128->menable, riva128); - timer_add(riva128_nvclk_poll, &riva128->nvtime, &riva128->nvenable, riva128); + timer_add(riva128_mclk_poll, &riva128->mtime, &timer_one, riva128); + timer_add(riva128_nvclk_poll, &riva128->nvtime, &timer_one, riva128); riva128->svga.vblank_start = riva128_vblank_start; @@ -3422,7 +3506,7 @@ void *rivatnt2_init(device_t *info) riva128->i2c.addrbits = 0; riva128->i2c.databits = 0; - riva128->i2c.busy = 0; + riva128->i2c.state = I2C_STOP; uint8_t edid_rom[128] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -3449,11 +3533,11 @@ void *rivatnt2_init(device_t *info) } } - riva128->menable = 0; - riva128->nvenable = 0; + riva128->menable = 1; + riva128->nvenable = 1; - timer_add(riva128_mclk_poll, &riva128->mtime, &riva128->menable, riva128); - timer_add(riva128_nvclk_poll, &riva128->nvtime, &riva128->nvenable, riva128); + timer_add(riva128_mclk_poll, &riva128->mtime, &timer_one, riva128); + timer_add(riva128_nvclk_poll, &riva128->nvtime, &timer_one, riva128); riva128->svga.vblank_start = riva128_vblank_start; From 8b3d51d3b77d532e1d0c5420e87c77ddea85f7a5 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 26 Feb 2018 22:18:31 +0100 Subject: [PATCH 2/9] Fixed include in nvr.c. --- src/nvr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/nvr.c b/src/nvr.c index 2bcafd96f..6d20dff8e 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -186,15 +186,15 @@ * (DS12887A) which implemented a "century" register to be * compatible with Y2K. * - * Version: @(#)nvr.c 1.0.14 2017/12/03 + * Version: @(#)nvr.c 1.0.15 2018/02/26 * * Authors: Miran Grca, * Mahod, * Fred N. van Kempen, * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -202,7 +202,7 @@ #include #include #include -#include "86Box.h" +#include "86box.h" #include "pic.h" #include "pit.h" #include "timer.h" From ffc7ee4ccd90689585218a355ef4ed4797b3510d Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Feb 2018 23:55:28 +0100 Subject: [PATCH 3/9] Ported over the CD-ROM, Iomega ZIP, and RTC fixes from PCem and disabled Iomega ZIP logging. --- src/cdrom/cdrom.c | 49 +++++++++++++++++++--------------------------- src/cdrom/cdrom.h | 1 + src/disk/hdc_ide.c | 5 ++++- src/nvr_at.c | 10 +++++++--- src/zip.c | 38 ++++++++++++++++------------------- src/zip.h | 3 ++- 6 files changed, 51 insertions(+), 55 deletions(-) diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index e72c2f890..65743bead 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -9,7 +9,7 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)cdrom.c 1.0.32 2018/02/25 + * Version: @(#)cdrom.c 1.0.33 2018/02/27 * * Author: Miran Grca, * @@ -684,6 +684,7 @@ uint32_t cdrom_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, void cdrom_update_request_length(uint8_t id, int len, int block_len) { uint32_t bt; + cdrom[id].max_transfer_len = cdrom[id].request_length; /* For media access commands, make sure the requested DRQ length matches the block length. */ switch (cdrom[id].current_cdb[0]) { @@ -692,8 +693,8 @@ void cdrom_update_request_length(uint8_t id, int len, int block_len) case 0xa8: case 0xb9: case 0xbe: - if (cdrom[id].request_length < block_len) - cdrom[id].request_length = block_len; + if (cdrom[id].max_transfer_len < block_len) + cdrom[id].max_transfer_len = block_len; bt = (cdrom[id].requested_blocks * block_len); if (len > bt) len = bt; @@ -702,11 +703,13 @@ void cdrom_update_request_length(uint8_t id, int len, int block_len) break; } /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ - if ((cdrom[id].request_length & 1) && (cdrom[id].request_length < len)) - cdrom[id].request_length &= 0xfffe; + if ((cdrom[id].max_transfer_len & 1) && (cdrom[id].max_transfer_len < len)) + cdrom[id].max_transfer_len &= 0xfffe; /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ - if (len <= cdrom[id].request_length) - cdrom[id].request_length = len; + if (!cdrom[id].max_transfer_len) + cdrom[id].max_transfer_len = 65534; + if (len <= cdrom[id].max_transfer_len) + cdrom[id].max_transfer_len = len; return; } @@ -765,13 +768,6 @@ static void cdrom_command_write_dma(uint8_t id) cdrom_command_common(id); } -static int cdrom_request_length_is_zero(uint8_t id) -{ - if ((cdrom[id].request_length == 0) && (cdrom_drives[id].bus_type < CDROM_BUS_SCSI)) - return 1; - return 0; -} - /* id = Current CD-ROM device ID; len = Total transfer length; block_len = Length of a single block (why does it matter?!); @@ -786,7 +782,7 @@ static void cdrom_data_command_finish(uint8_t id, int len, int block_len, int al len = alloc_len; } } - if (cdrom_request_length_is_zero(id) || (len == 0) || (cdrom_current_mode(id) == 0)) { + if ((len == 0) || (cdrom_current_mode(id) == 0)) { if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI) { cdrom[id].packet_len = 0; } @@ -2675,9 +2671,9 @@ void cdrom_pio_request(uint8_t id, uint8_t out) /* If less than (packet length) bytes are remaining, update packet length accordingly. */ - if ((cdrom[id].packet_len - cdrom[id].pos) < (cdrom[id].request_length)) - cdrom[id].request_length = cdrom[id].packet_len - cdrom[id].pos; - cdrom_log("CD-ROM %i: Packet length %i, request length %i\n", id, cdrom[id].packet_len, cdrom[id].request_length); + if ((cdrom[id].packet_len - cdrom[id].pos) < (cdrom[id].max_transfer_len)) + cdrom[id].max_transfer_len = cdrom[id].packet_len - cdrom[id].pos; + cdrom_log("CD-ROM %i: Packet length %i, request length %i\n", id, cdrom[id].packet_len, cdrom[id].max_transfer_len); old_pos = cdrom[id].pos; cdrom[id].packet_status = out ? CDROM_PHASE_DATA_OUT : CDROM_PHASE_DATA_IN; @@ -2732,8 +2728,6 @@ int cdrom_read_from_dma(uint8_t id) int ret = 0; - int in_data_length = 0; - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) ret = cdrom_read_from_scsi_dma(cdrom_drives[id].scsi_device_id, cdrom_drives[id].scsi_device_lun); else @@ -2742,13 +2736,10 @@ int cdrom_read_from_dma(uint8_t id) if (!ret) return 0; - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - in_data_length = *BufLen; - cdrom_log("CD-ROM %i: SCSI Input data length: %i\n", id, in_data_length); - } else { - in_data_length = cdrom[id].request_length; - cdrom_log("CD-ROM %i: ATAPI Input data length: %i\n", id, in_data_length); - } + if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) + cdrom_log("CD-ROM %i: SCSI Input data length: %i\n", id, *BufLen); + else + cdrom_log("CD-ROM %i: ATAPI Input data length: %i\n", id, cdrom[id].packet_len); ret = cdrom_phase_data_out(id); if (!ret) { @@ -2936,7 +2927,7 @@ uint32_t cdrom_read(uint8_t channel, int length) } if (cdrom[id].packet_status == CDROM_PHASE_DATA_IN) { - if ((cdrom[id].request_pos >= cdrom[id].request_length) || (cdrom[id].pos >= cdrom[id].packet_len)) { + if ((cdrom[id].request_pos >= cdrom[id].max_transfer_len) || (cdrom[id].pos >= cdrom[id].packet_len)) { /* Time for a DRQ. */ // cdrom_log("CD-ROM %i: Issuing read callback\n", id); cdrom_pio_request(id, 0); @@ -2992,7 +2983,7 @@ void cdrom_write(uint8_t channel, uint32_t val, int length) } if (cdrom[id].packet_status == CDROM_PHASE_DATA_OUT) { - if ((cdrom[id].request_pos >= cdrom[id].request_length) || (cdrom[id].pos >= cdrom[id].packet_len)) { + if ((cdrom[id].request_pos >= cdrom[id].max_transfer_len) || (cdrom[id].pos >= cdrom[id].packet_len)) { /* Time for a DRQ. */ cdrom_pio_request(id, 1); } diff --git a/src/cdrom/cdrom.h b/src/cdrom/cdrom.h index ca6650621..bf208267f 100644 --- a/src/cdrom/cdrom.h +++ b/src/cdrom/cdrom.h @@ -103,6 +103,7 @@ typedef struct { uint8_t error; uint8_t features; uint16_t request_length; + uint16_t max_transfer_len; uint8_t status; uint8_t phase; diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index d215ec77c..0e2b8d09c 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -9,7 +9,7 @@ * Implementation of the IDE emulation for hard disks and ATAPI * CD-ROM devices. * - * Version: @(#)hdc_ide.c 1.0.28 2018/02/25 + * Version: @(#)hdc_ide.c 1.0.29 2018/02/27 * * Authors: Sarah Walker, * Miran Grca, @@ -447,6 +447,7 @@ static void ide_atapi_identify(IDE *ide) ide->buffer[48] = 1; /*Dword transfers supported*/ ide->buffer[49] = 0x200; /* LBA supported */ ide->buffer[51] = 2 << 8; /*PIO timing mode*/ + ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ if (PCI && (ide->board < 2) && (cdrom_drives[cdrom_id].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) { @@ -499,6 +500,8 @@ static void ide_atapi_zip_identify(IDE *ide) ide->buffer[48] = 1; /*Dword transfers supported*/ ide->buffer[51] = 2 << 8; /*PIO timing mode*/ + ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ + if (PCI && (ide->board < 2) && (zip_drives[zip_id].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) { ide->buffer[49] |= 0x100; /* DMA supported */ diff --git a/src/nvr_at.c b/src/nvr_at.c index 2f470b0f6..131d1415c 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -14,13 +14,13 @@ * of those batteries would create corrosion issues later on * in mainboard life... * - * Version: @(#)nvr_at.c 1.0.8 2017/11/22 + * Version: @(#)nvr_at.c 1.0.9 2018/02/27 * * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016,2017 Miran Grca. - * Copyright 2017 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. */ #include #include @@ -45,6 +45,8 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) { nvr_t *nvr = (nvr_t *)priv; + cycles -= ISA_CYCLES(8); + if (! (addr & 1)) { nvr->addr = (val & nvr->mask); if (!(machines[machine].flags & MACHINE_MCA) && (romset != ROM_IBMPS1_2133)) @@ -64,6 +66,8 @@ nvr_read(uint16_t addr, void *priv) nvr_t *nvr = (nvr_t *)priv; uint8_t ret; + cycles -= ISA_CYCLES(8); + if (addr & 1) { /* Read from the chip's registers. */ ret = (*nvr->get)(nvr, nvr->addr); diff --git a/src/zip.c b/src/zip.c index f6726f413..0cbd43ce5 100644 --- a/src/zip.c +++ b/src/zip.c @@ -9,7 +9,7 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)zip.c 1.0.5 2018/02/15 + * Version: @(#)zip.c 1.0.6 2018/02/27 * * Author: Miran Grca, * @@ -455,7 +455,6 @@ static const mode_sense_pages_t zip_250_mode_sense_pages_changeable = static mode_sense_pages_t zip_mode_sense_pages_saved[ZIP_NUM]; -#define ENABLE_ZIP_LOG 1 #ifdef ENABLE_ZIP_LOG int zip_do_log = ENABLE_ZIP_LOG; #endif @@ -903,14 +902,18 @@ uint32_t zip_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, ui void zip_update_request_length(uint8_t id, int len, int block_len) { uint32_t bt; + if (!zip[id].request_length) + zip[id].max_transfer_len = 65534; + else + zip[id].max_transfer_len = zip[id].request_length; /* For media access commands, make sure the requested DRQ length matches the block length. */ switch (zip[id].current_cdb[0]) { case 0x08: case 0x28: case 0xa8: - if (zip[id].request_length < block_len) - zip[id].request_length = block_len; + if (zip[id].max_transfer_len < block_len) + zip[id].max_transfer_len = block_len; bt = (zip[id].requested_blocks * block_len); if (len > bt) len = bt; @@ -919,11 +922,11 @@ void zip_update_request_length(uint8_t id, int len, int block_len) break; } /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ - if ((zip[id].request_length & 1) && (zip[id].request_length < len)) - zip[id].request_length &= 0xfffe; + if ((zip[id].max_transfer_len & 1) && (zip[id].max_transfer_len < len)) + zip[id].max_transfer_len &= 0xfffe; /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ - if (len <= zip[id].request_length) - zip[id].request_length = len; + if (len <= zip[id].max_transfer_len) + zip[id].max_transfer_len = len; return; } @@ -982,13 +985,6 @@ static void zip_command_write_dma(uint8_t id) zip_command_common(id); } -static int zip_request_length_is_zero(uint8_t id) -{ - if ((zip[id].request_length == 0) && (zip_drives[id].bus_type < ZIP_BUS_SCSI)) - return 1; - return 0; -} - /* id = Current ZIP device ID; len = Total transfer length; block_len = Length of a single block (why does it matter?!); @@ -1003,7 +999,7 @@ static void zip_data_command_finish(uint8_t id, int len, int block_len, int allo len = alloc_len; } } - if (zip_request_length_is_zero(id) || (len == 0) || (zip_current_mode(id) == 0)) { + if ((len == 0) || (zip_current_mode(id) == 0)) { if (zip_drives[id].bus_type != ZIP_BUS_SCSI) { zip[id].packet_len = 0; } @@ -2194,8 +2190,8 @@ void zip_pio_request(uint8_t id, uint8_t out) /* If less than (packet length) bytes are remaining, update packet length accordingly. */ - if ((zip[id].packet_len - zip[id].pos) < (zip[id].request_length)) - zip[id].request_length = zip[id].packet_len - zip[id].pos; + if ((zip[id].packet_len - zip[id].pos) < (zip[id].max_transfer_len)) + zip[id].max_transfer_len = zip[id].packet_len - zip[id].pos; old_pos = zip[id].pos; zip[id].packet_status = out ? ZIP_PHASE_DATA_OUT : ZIP_PHASE_DATA_IN; @@ -2263,7 +2259,7 @@ int zip_read_from_dma(uint8_t id) in_data_length = *BufLen; zip_log("ZIP %i: SCSI Input data length: %i\n", id, in_data_length); } else { - in_data_length = zip[id].request_length; + in_data_length = zip[id].max_transfer_len; zip_log("ZIP %i: ATAPI Input data length: %i\n", id, in_data_length); } @@ -2453,7 +2449,7 @@ uint32_t zip_read(uint8_t channel, int length) } if (zip[id].packet_status == ZIP_PHASE_DATA_IN) { - if ((zip[id].request_pos >= zip[id].request_length) || (zip[id].pos >= zip[id].packet_len)) { + if ((zip[id].request_pos >= zip[id].max_transfer_len) || (zip[id].pos >= zip[id].packet_len)) { /* Time for a DRQ. */ // zip_log("ZIP %i: Issuing read callback\n", id); zip_pio_request(id, 0); @@ -2509,7 +2505,7 @@ void zip_write(uint8_t channel, uint32_t val, int length) } if (zip[id].packet_status == ZIP_PHASE_DATA_OUT) { - if ((zip[id].request_pos >= zip[id].request_length) || (zip[id].pos >= zip[id].packet_len)) { + if ((zip[id].request_pos >= zip[id].max_transfer_len) || (zip[id].pos >= zip[id].packet_len)) { /* Time for a DRQ. */ zip_pio_request(id, 1); } diff --git a/src/zip.h b/src/zip.h index be5401f7d..5705b4a0a 100644 --- a/src/zip.h +++ b/src/zip.h @@ -9,7 +9,7 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)zip.h 1.0.1 2018/01/26 + * Version: @(#)zip.h 1.0.2 2018/02/27 * * Author: Miran Grca, * @@ -74,6 +74,7 @@ typedef struct { uint8_t error; uint8_t features; uint16_t request_length; + uint16_t max_transfer_len; uint8_t status; uint8_t phase; From 9d09c1b405b364e717f0264e45b72483877346b7 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 1 Mar 2018 23:03:19 +0100 Subject: [PATCH 4/9] Implemented the mapping peculiarities needed by the CL-GD 5436, fixes the Windows 98 SE CL-GD 5436 PCI driver; Properly fixed the Windows 9x shutdown screen on the Cirrus Logic cards without the need for hacks. --- src/video/vid_cl54xx.c | 514 ++++++++++++++++++++++++++++++++++------- 1 file changed, 428 insertions(+), 86 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 294410aa7..f9a42b155 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -9,7 +9,7 @@ * Emulation of select Cirrus Logic cards (CL-GD 5428, * CL-GD 5429, 5430, 5434 and 5436 are supported). * - * Version: @(#)vid_cl_54xx.c 1.0.4 2018/02/25 + * Version: @(#)vid_cl_54xx.c 1.0.6 2018/03/01 * * Authors: Sarah Walker, * Barry Rodewald, @@ -240,26 +240,6 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) if (gd54xx->ramdac.state == 4) { gd54xx->ramdac.state = 0; gd54xx->ramdac.ctrl = val; - - switch (svga->seqregs[0x07] & CIRRUS_SR7_BPP_MASK) - { - case CIRRUS_SR7_BPP_8: - svga->bpp = 8; - break; - case CIRRUS_SR7_BPP_16_DOUBLEVCLK: - case CIRRUS_SR7_BPP_16: - if (gd54xx->ramdac.ctrl & 0x01) - svga->bpp = 16; - else - svga->bpp = 15; - break; - case CIRRUS_SR7_BPP_24: - svga->bpp = 24; - break; - case CIRRUS_SR7_BPP_32: - svga->bpp = 32; - break; - } svga_recalctimings(svga); return; } @@ -282,6 +262,15 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) return; } + if (svga->gdcaddr == 6) { + if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) { + svga->gdcreg[6] = val; + gd543x_recalc_mapping(gd54xx); + } + svga->gdcreg[6] = val; + return; + } + if (svga->gdcaddr > 8) { svga->gdcreg[svga->gdcaddr & 0x3f] = val; switch (svga->gdcaddr) { @@ -570,18 +559,32 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) size = 2 * 1024 * 1024; } else if (gd54xx->pci) { base = gd54xx->lfb_base; - size = 4 * 1024 * 1024; + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5436) + size = 16 * 1024 * 1024; + else + size = 4 * 1024 * 1024; } else { /*VLB*/ base = 128*1024*1024; - size = 4 * 1024 * 1024; + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5436) + size = 16 * 1024 * 1024; + else + size = 4 * 1024 * 1024; } mem_mapping_disable(&svga->mapping); mem_mapping_set_addr(&gd54xx->linear_mapping, base, size); svga->linear_base = base; - if (svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) - mem_mapping_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x00100); - else + if (svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) { + if (svga->seqregs[0x17] & 0x40) { + if (size >= (4 * 1024 * 1024)) + mem_mapping_disable(&gd54xx->mmio_mapping); /* MMIO is handled in the linear read/write functions */ + else { + mem_mapping_set_addr(&gd54xx->linear_mapping, base, size - 256); + mem_mapping_set_addr(&gd54xx->mmio_mapping, base + size - 256, 0x00100); + } + } else + mem_mapping_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x00100); + } else mem_mapping_disable(&gd54xx->mmio_mapping); } } @@ -592,41 +595,48 @@ gd54xx_recalctimings(svga_t *svga) { gd54xx_t *gd54xx = (gd54xx_t *)svga->p; uint8_t clocksel; - - svga->rowoffset = (svga->crtc[0x13]) | ((svga->crtc[0x1b] & 0x10) << 4); - - svga->interlace = (svga->crtc[0x1a] & 0x01); + + svga->rowoffset = (svga->crtc[0x13]) | ((svga->crtc[0x1b] & 0x10) << 4); + + svga->interlace = (svga->crtc[0x1a] & 0x01); + + if (svga->seqregs[7] & 0x01) { + svga->render = svga_render_8bpp_highres; + svga->bpp = 8; + } else if (svga->gdcreg[5] & 0x40) { + svga->render = svga_render_8bpp_lowres; + svga->bpp = 8; + } svga->ma_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15); - if (svga->seqregs[0x07] & CIRRUS_SR7_BPP_SVGA) - { - if (!(svga->gdcreg[5] & 0x60)) /*This is needed for the shutdown screens on Win9x to render correctly*/ - svga->gdcreg[5] = 0x60; - - switch (svga->bpp) - { - case 8: - svga->render = svga_render_8bpp_highres; - break; - - case 15: - svga->render = svga_render_15bpp_highres; - break; - - case 16: - svga->render = svga_render_16bpp_highres; - break; - - case 24: - svga->render = svga_render_24bpp_highres; - break; - - case 32: - svga->render = svga_render_32bpp_highres; - svga->rowoffset *= 2; - break; + if (gd54xx->ramdac.ctrl & 0x80) { + if (gd54xx->ramdac.ctrl & 0x40) { + switch (gd54xx->ramdac.ctrl & 0xf) { + case 0x0: + svga->render = svga_render_15bpp_highres; + svga->bpp = 15; + break; + case 0x1: + svga->render = svga_render_16bpp_highres; + svga->bpp = 16; + break; + case 0x5: + if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) && (svga->seqregs[7] & 8)) { + svga->render = svga_render_32bpp_highres; + svga->bpp = 32; + if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436) + svga->rowoffset *= 2; + } else { + svga->render = svga_render_24bpp_highres; + svga->bpp = 24; + } + break; } + } else { + svga->render = svga_render_15bpp_highres; + svga->bpp = 15; + } } clocksel = (svga->miscout >> 2) & 3; @@ -1077,12 +1087,207 @@ gd54xx_write_linear(uint32_t addr, uint8_t val, gd54xx_t *gd54xx) } -static void +static uint8_t +gd54xx_get_aperture(uint32_t addr) +{ + uint32_t ap = addr >> 22; + return (uint8_t) (ap & 0x03); +} + + +static uint8_t +gd54xx_readb_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + gd54xx_t *gd54xx = (gd54xx_t *)svga->p; + + uint8_t ap = gd54xx_get_aperture(addr); + addr &= 0x003fffff; /* 4 MB mask */ + + switch (ap) { + case 0: + default: + break; + case 1: + /* 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2 */ + addr ^= 0x00000001; + break; + case 2: + /* 0 -> 3, 1 -> 2, 2 -> 1, 3 -> 0 */ + addr ^= 0x00000003; + break; + case 3: + return 0xff; + } + + if ((addr & 0x003fff00) == 0x003fff00) { + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & 0x40)) + return gd543x_mmio_read(addr & 0x000000ff, gd54xx); + } + + return svga_read_linear(addr, p); +} + + +static uint16_t +gd54xx_readw_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + gd54xx_t *gd54xx = (gd54xx_t *)svga->p; + + uint8_t ap = gd54xx_get_aperture(addr); + uint16_t temp, temp2; + + addr &= 0x003fffff; /* 4 MB mask */ + + if ((addr & 0x003fff00) == 0x003fff00) { + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & 0x40)) { + if (ap == 2) + addr ^= 0x00000002; + + temp = gd543x_mmio_readw(addr & 0x000000ff, gd54xx); + + switch(ap) { + case 0: + default: + return temp; + case 1: + case 2: + temp2 = temp >> 8; + temp2 |= ((temp & 0xff) << 8); + return temp; + case 3: + return 0xffff; + } + } + } + + switch (ap) { + case 0: + default: + return svga_readw_linear(addr, p); + case 2: + /* 0 -> 3, 1 -> 2, 2 -> 1, 3 -> 0 */ + addr ^= 0x00000002; + case 1: + temp = svga_readb_linear(addr + 1, p); + temp |= (svga_readb_linear(addr, p) << 8); + + if (svga->fast) { + cycles -= video_timing_read_w; + cycles_lost += video_timing_read_w; + } + + return temp; + case 3: + return 0xffff; + } +} + + +static uint32_t +gd54xx_readl_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + gd54xx_t *gd54xx = (gd54xx_t *)svga->p; + + uint8_t ap = gd54xx_get_aperture(addr); + uint32_t temp, temp2; + + addr &= 0x003fffff; /* 4 MB mask */ + + if ((addr & 0x003fff00) == 0x003fff00) { + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & 0x40)) { + temp = gd543x_mmio_readl(addr & 0x000000ff, gd54xx); + + switch(ap) { + case 0: + default: + return temp; + case 1: + temp2 = temp >> 24; + temp2 |= ((temp >> 16) & 0xff) << 8; + temp2 |= ((temp >> 8) & 0xff) << 16; + temp2 |= (temp & 0xff) << 24; + + return temp2; + case 2: + temp2 = (temp >> 8) & 0xff; + temp2 |= (temp & 0xff) << 8; + temp2 = ((temp >> 24) & 0xff) << 16; + temp2 = ((temp >> 16) & 0xff) << 24; + + return temp2; + case 3: + return 0xffffffff; + } + } + } + + switch (ap) { + case 0: + default: + return svga_readw_linear(addr, p); + case 1: + temp = svga_readb_linear(addr + 1, p); + temp |= (svga_readb_linear(addr, p) << 8); + temp |= (svga_readb_linear(addr + 3, p) << 16); + temp |= (svga_readb_linear(addr + 2, p) << 24); + + if (svga->fast) { + cycles -= video_timing_read_l; + cycles_lost += video_timing_read_l; + } + + return temp; + case 2: + temp = svga_readb_linear(addr + 3, p); + temp |= (svga_readb_linear(addr + 2, p) << 8); + temp |= (svga_readb_linear(addr + 1, p) << 16); + temp |= (svga_readb_linear(addr, p) << 24); + + if (svga->fast) { + cycles -= video_timing_read_l; + cycles_lost += video_timing_read_l; + } + + return temp; + case 3: + return 0xffffffff; + } +} + + +static void gd54xx_writeb_linear(uint32_t addr, uint8_t val, void *p) { svga_t *svga = (svga_t *)p; gd54xx_t *gd54xx = (gd54xx_t *)svga->p; + uint8_t ap = gd54xx_get_aperture(addr); + addr &= 0x003fffff; /* 4 MB mask */ + + switch (ap) { + case 0: + default: + break; + case 1: + /* 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2 */ + addr ^= 0x00000001; + break; + case 2: + /* 0 -> 3, 1 -> 2, 2 -> 1, 3 -> 0 */ + addr ^= 0x00000003; + break; + case 3: + return; + } + + if ((addr & 0x003fff00) == 0x003fff00) { + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & 0x40)) + gd543x_mmio_write(addr & 0x000000ff, val, gd54xx); + } + if (gd54xx->blt.sys_tx) { if (gd54xx->blt.mode == CIRRUS_BLTMODE_MEMSYSSRC) { gd54xx->blt.sys_buf &= ~(0xff << (gd54xx->blt.sys_cnt * 8)); @@ -1109,17 +1314,70 @@ gd54xx_writew_linear(uint32_t addr, uint16_t val, void *p) svga_t *svga = (svga_t *)p; gd54xx_t *gd54xx = (gd54xx_t *)svga->p; + uint8_t ap = gd54xx_get_aperture(addr); + uint16_t temp; + + if ((addr & 0x003fff00) == 0x003fff00) { + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & 0x40)) { + switch(ap) { + case 0: + default: + gd543x_mmio_writew(addr & 0x000000ff, val, gd54xx); + return; + case 2: + addr ^= 0x00000002; + case 1: + temp = (val >> 8); + temp |= ((val & 0xff) << 8); + gd543x_mmio_writew(addr & 0x000000ff, temp, gd54xx); + case 3: + return; + } + } + } + if (gd54xx->blt.sys_tx) { gd54xx_writeb_linear(addr, val, svga); gd54xx_writeb_linear(addr+1, val >> 8, svga); return; } - if (svga->writemode < 4) - svga_writew_linear(addr, val, svga); - else { - gd54xx_write_linear(addr, val & 0xff, gd54xx); - gd54xx_write_linear(addr+1, val >> 8, gd54xx); + addr &= 0x003fffff; /* 4 MB mask */ + + if (svga->writemode < 4) { + switch(ap) { + case 0: + default: + svga_writew_linear(addr, val, svga); + return; + case 2: + addr ^= 0x00000002; + case 1: + svga_writeb_linear(addr + 1, val & 0xff, svga); + svga_writeb_linear(addr, val >> 8, svga); + + if (svga->fast) { + cycles -= video_timing_write_w; + cycles_lost += video_timing_write_w; + } + case 3: + return; + } + } else { + switch(ap) { + case 0: + default: + gd54xx_write_linear(addr, val & 0xff, gd54xx); + gd54xx_write_linear(addr + 1, val >> 8, gd54xx); + return; + case 2: + addr ^= 0x00000002; + case 1: + gd54xx_write_linear(addr + 1, val & 0xff, gd54xx); + gd54xx_write_linear(addr, val >> 8, gd54xx); + case 3: + return; + } } } @@ -1130,6 +1388,36 @@ gd54xx_writel_linear(uint32_t addr, uint32_t val, void *p) svga_t *svga = (svga_t *)p; gd54xx_t *gd54xx = (gd54xx_t *)svga->p; + uint8_t ap = gd54xx_get_aperture(addr); + uint32_t temp; + + if ((addr & 0x003fff00) == 0x003fff00) { + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x17] & 0x40)) { + switch(ap) { + case 0: + default: + gd543x_mmio_writel(addr & 0x000000ff, val, gd54xx); + return; + case 2: + temp = (val >> 24); + temp |= ((val >> 16) & 0xff) << 8; + temp |= ((val >> 8) & 0xff) << 16; + temp |= (val & 0xff) << 24; + gd543x_mmio_writel(addr & 0x000000ff, temp, gd54xx); + return; + case 1: + temp = ((val >> 8) & 0xff); + temp |= (val & 0xff) << 8; + temp |= (val >> 24) << 16; + temp |= ((val >> 16) & 0xff) << 24; + gd543x_mmio_writel(addr & 0x000000ff, temp, gd54xx); + return; + case 3: + return; + } + } + } + if (gd54xx->blt.sys_tx) { gd54xx_writeb_linear(addr, val, svga); gd54xx_writeb_linear(addr+1, val >> 8, svga); @@ -1137,14 +1425,57 @@ gd54xx_writel_linear(uint32_t addr, uint32_t val, void *p) gd54xx_writeb_linear(addr+3, val >> 24, svga); return; } + + addr &= 0x003fffff; /* 4 MB mask */ - if (svga->writemode < 4) - svga_writel_linear(addr, val, svga); - else { - gd54xx_write_linear(addr, val & 0xff, gd54xx); - gd54xx_write_linear(addr+1, val >> 8, gd54xx); - gd54xx_write_linear(addr+2, val >> 16, gd54xx); - gd54xx_write_linear(addr+3, val >> 24, gd54xx); + if (svga->writemode < 4) { + switch(ap) { + case 0: + default: + svga_writel_linear(addr, val, svga); + return; + case 1: + svga_writeb_linear(addr + 1, val & 0xff, svga); + svga_writeb_linear(addr, val >> 8, svga); + svga_writeb_linear(addr + 3, val >> 16, svga); + svga_writeb_linear(addr + 2, val >> 24, svga); + return; + case 2: + svga_writeb_linear(addr + 3, val & 0xff, svga); + svga_writeb_linear(addr + 2, val >> 8, svga); + svga_writeb_linear(addr + 1, val >> 16, svga); + svga_writeb_linear(addr, val >> 24, svga); + case 3: + return; + } + + if (svga->fast) { + cycles -= video_timing_write_l; + cycles_lost += video_timing_write_l; + } + } else { + switch(ap) { + case 0: + default: + gd54xx_write_linear(addr, val & 0xff, gd54xx); + gd54xx_write_linear(addr+1, val >> 8, gd54xx); + gd54xx_write_linear(addr+2, val >> 16, gd54xx); + gd54xx_write_linear(addr+3, val >> 24, gd54xx); + return; + case 1: + gd54xx_write_linear(addr + 1, val & 0xff, gd54xx); + gd54xx_write_linear(addr, val >> 8, gd54xx); + gd54xx_write_linear(addr + 3, val >> 16, gd54xx); + gd54xx_write_linear(addr + 2, val >> 24, gd54xx); + return; + case 2: + gd54xx_write_linear(addr + 3, val & 0xff, gd54xx); + gd54xx_write_linear(addr + 2, val >> 8, gd54xx); + gd54xx_write_linear(addr + 1, val >> 16, gd54xx); + gd54xx_write_linear(addr, val >> 24, gd54xx); + case 3: + return; + } } } @@ -1184,13 +1515,23 @@ gd54xx_readl(uint32_t addr, void *p) } +static int +gd543x_do_mmio(svga_t *svga, uint32_t addr) +{ + if (svga->seqregs[0x17] & 0x40) + return 1; + else + return ((addr & ~0xff) == 0xb8000); +} + + static void gd543x_mmio_write(uint32_t addr, uint8_t val, void *p) { gd54xx_t *gd54xx = (gd54xx_t *)p; svga_t *svga = &gd54xx->svga; - if ((addr & ~0xff) == 0xb8000) { + if (gd543x_do_mmio(svga, addr)) { switch (addr & 0xff) { case 0x00: if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) @@ -1321,23 +1662,19 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *p) break; case 0x1c: - if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5434) - gd54xx->blt.trans_col = (gd54xx->blt.trans_col & 0xff00) | val; + gd54xx->blt.trans_col = (gd54xx->blt.trans_col & 0xff00) | val; break; case 0x1d: - if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5434) - gd54xx->blt.trans_col = (gd54xx->blt.trans_col & 0x00ff) | (val << 8); + gd54xx->blt.trans_col = (gd54xx->blt.trans_col & 0x00ff) | (val << 8); break; case 0x20: - if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5434) - gd54xx->blt.trans_mask = (gd54xx->blt.trans_mask & 0xff00) | val; + gd54xx->blt.trans_mask = (gd54xx->blt.trans_mask & 0xff00) | val; break; case 0x21: - if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5434) - gd54xx->blt.trans_mask = (gd54xx->blt.trans_mask & 0x00ff) | (val << 8); + gd54xx->blt.trans_mask = (gd54xx->blt.trans_mask & 0x00ff) | (val << 8); break; case 0x40: @@ -1364,8 +1701,9 @@ static void gd543x_mmio_writew(uint32_t addr, uint16_t val, void *p) { gd54xx_t *gd54xx = (gd54xx_t *)p; + svga_t *svga = &gd54xx->svga; - if ((addr & ~0xff) == 0xb8000) { + if (gd543x_do_mmio(svga, addr)) { gd543x_mmio_write(addr, val & 0xff, gd54xx); gd543x_mmio_write(addr+1, val >> 8, gd54xx); } else if (gd54xx->mmio_vram_overlap) { @@ -1379,8 +1717,9 @@ static void gd543x_mmio_writel(uint32_t addr, uint32_t val, void *p) { gd54xx_t *gd54xx = (gd54xx_t *)p; + svga_t *svga = &gd54xx->svga; - if ((addr & ~0xff) == 0xb8000) { + if (gd543x_do_mmio(svga, addr)) { gd543x_mmio_write(addr, val & 0xff, gd54xx); gd543x_mmio_write(addr+1, val >> 8, gd54xx); gd543x_mmio_write(addr+2, val >> 16, gd54xx); @@ -1398,8 +1737,9 @@ static uint8_t gd543x_mmio_read(uint32_t addr, void *p) { gd54xx_t *gd54xx = (gd54xx_t *)p; + svga_t *svga = &gd54xx->svga; - if ((addr & ~0xff) == 0xb8000) { + if (gd543x_do_mmio(svga, addr)) { switch (addr & 0xff) { case 0x40: /*BLT status*/ return 0; @@ -1416,8 +1756,9 @@ static uint16_t gd543x_mmio_readw(uint32_t addr, void *p) { gd54xx_t *gd54xx = (gd54xx_t *)p; + svga_t *svga = &gd54xx->svga; - if ((addr & ~0xff) == 0xb8000) + if (gd543x_do_mmio(svga, addr)) return gd543x_mmio_read(addr, gd54xx) | (gd543x_mmio_read(addr+1, gd54xx) << 8); else if (gd54xx->mmio_vram_overlap) return gd54xx_read(addr, gd54xx) | (gd54xx_read(addr+1, gd54xx) << 8); @@ -1429,8 +1770,9 @@ static uint32_t gd543x_mmio_readl(uint32_t addr, void *p) { gd54xx_t *gd54xx = (gd54xx_t *)p; + svga_t *svga = &gd54xx->svga; - if ((addr & ~0xff) == 0xb8000) + if (gd543x_do_mmio(svga, addr)) return gd543x_mmio_read(addr, gd54xx) | (gd543x_mmio_read(addr+1, gd54xx) << 8) | (gd543x_mmio_read(addr+2, gd54xx) << 16) | (gd543x_mmio_read(addr+3, gd54xx) << 24); else if (gd54xx->mmio_vram_overlap) return gd54xx_read(addr, gd54xx) | (gd54xx_read(addr+1, gd54xx) << 8) | (gd54xx_read(addr+2, gd54xx) << 16) | (gd54xx_read(addr+3, gd54xx) << 24); @@ -1513,7 +1855,7 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga) mem_mapping_set_p(&gd54xx->linear_mapping, svga); } gd543x_recalc_mapping(gd54xx); - } + } } else if (gd54xx->blt.height_internal == 0xffff) return; @@ -1959,7 +2301,7 @@ static void mem_mapping_set_p(&svga->mapping, gd54xx); mem_mapping_add(&gd54xx->mmio_mapping, 0, 0, gd543x_mmio_read, gd543x_mmio_readw, gd543x_mmio_readl, gd543x_mmio_write, gd543x_mmio_writew, gd543x_mmio_writel, NULL, 0, gd54xx); - mem_mapping_add(&gd54xx->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear, NULL, 0, svga); + mem_mapping_add(&gd54xx->linear_mapping, 0, 0, gd54xx_readb_linear, gd54xx_readw_linear, gd54xx_readl_linear, gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear, NULL, 0, svga); io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); From 27c49ad8981c0d8128afb9e91c9aea5281ae8af3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 1 Mar 2018 23:05:59 +0100 Subject: [PATCH 5/9] Committed the vid_svga.c/h changes that I forgot before. --- src/video/vid_svga.c | 39 ++++++++++++++++++++++++++++++++++++++- src/video/vid_svga.h | 4 +++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 87b273323..24459ea29 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -11,7 +11,7 @@ * This is intended to be used by another SVGA driver, * and not as a card in it's own right. * - * Version: @(#)vid_svga.c 1.0.21 2018/02/24 + * Version: @(#)vid_svga.c 1.0.22 2018/03/01 * * Authors: Sarah Walker, * Miran Grca, @@ -1430,6 +1430,27 @@ uint32_t svga_readl(uint32_t addr, void *p) return *(uint32_t *)&svga->vram[addr & svga->vram_mask]; } +void svga_writeb_linear(uint32_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + + if (!svga->fast) + { + svga_write_linear(addr, val, p); + return; + } + + egawrites += 2; + + if (svga_output) pclog("Write LFBw %08X %04X\n", addr, val); + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + *(uint8_t *)&svga->vram[addr] = val; +} + void svga_writew_linear(uint32_t addr, uint16_t val, void *p) { svga_t *svga = (svga_t *)p; @@ -1482,6 +1503,22 @@ void svga_writel_linear(uint32_t addr, uint32_t val, void *p) *(uint32_t *)&svga->vram[addr] = val; } +uint8_t svga_readb_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + + if (!svga->fast) + return svga_read_linear(addr, p); + + egareads++; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; + + return *(uint8_t *)&svga->vram[addr & svga->vram_mask]; +} + uint16_t svga_readw_linear(uint32_t addr, void *p) { svga_t *svga = (svga_t *)p; diff --git a/src/video/vid_svga.h b/src/video/vid_svga.h index db9e22a7b..bf1189ed4 100644 --- a/src/video/vid_svga.h +++ b/src/video/vid_svga.h @@ -8,7 +8,7 @@ * * Generic SVGA handling. * - * Version: @(#)vid_svga.h 1.0.8 2018/02/24 + * Version: @(#)vid_svga.h 1.0.9 2018/03/01 * * Authors: Sarah Walker, * Miran Grca, @@ -172,9 +172,11 @@ void svga_write(uint32_t addr, uint8_t val, void *p); void svga_writew(uint32_t addr, uint16_t val, void *p); void svga_writel(uint32_t addr, uint32_t val, void *p); uint8_t svga_read_linear(uint32_t addr, void *p); +uint8_t svga_readb_linear(uint32_t addr, void *p); uint16_t svga_readw_linear(uint32_t addr, void *p); uint32_t svga_readl_linear(uint32_t addr, void *p); void svga_write_linear(uint32_t addr, uint8_t val, void *p); +void svga_writeb_linear(uint32_t addr, uint8_t val, void *p); void svga_writew_linear(uint32_t addr, uint16_t val, void *p); void svga_writel_linear(uint32_t addr, uint32_t val, void *p); From 0cc23a47694316b95fda27074333225a5a7baf56 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 2 Mar 2018 00:52:31 +0100 Subject: [PATCH 6/9] Fixed CL-GD 542x 2 MB aperture mapping. --- src/video/vid_cl54xx.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index f9a42b155..dcaeb06f4 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -9,7 +9,7 @@ * Emulation of select Cirrus Logic cards (CL-GD 5428, * CL-GD 5429, 5430, 5434 and 5436 are supported). * - * Version: @(#)vid_cl_54xx.c 1.0.6 2018/03/01 + * Version: @(#)vid_cl_54xx.c 1.0.7 2018/03/01 * * Authors: Sarah Walker, * Barry Rodewald, @@ -552,17 +552,20 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) uint32_t base, size; if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5429 || (!gd54xx->pci && !gd54xx->vlb)) { - base = (svga->seqregs[7] & 0xf0) << 16; - if (svga->gdcreg[0xb] & 0x20) + if (svga->gdcreg[0xb] & 0x20) { + base = (svga->seqregs[7] & 0xf0) << 16; size = 1 * 1024 * 1024; - else + } else { + base = (svga->seqregs[7] & 0xe0) << 16; size = 2 * 1024 * 1024; + } } else if (gd54xx->pci) { base = gd54xx->lfb_base; if (svga->crtc[0x27] == CIRRUS_ID_CLGD5436) size = 16 * 1024 * 1024; - else + else if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) size = 4 * 1024 * 1024; + else } else { /*VLB*/ base = 128*1024*1024; if (svga->crtc[0x27] == CIRRUS_ID_CLGD5436) From c8d331e15a26f7fa07f0c6d93bf4f3239db0f255 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 2 Mar 2018 00:55:52 +0100 Subject: [PATCH 7/9] Fixed a compile-breaking mistake in vid_cl54xx.c. --- src/video/vid_cl54xx.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index dcaeb06f4..5d8694ba2 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -9,7 +9,7 @@ * Emulation of select Cirrus Logic cards (CL-GD 5428, * CL-GD 5429, 5430, 5434 and 5436 are supported). * - * Version: @(#)vid_cl_54xx.c 1.0.7 2018/03/01 + * Version: @(#)vid_cl_54xx.c 1.0.8 2018/03/01 * * Authors: Sarah Walker, * Barry Rodewald, @@ -563,9 +563,8 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) base = gd54xx->lfb_base; if (svga->crtc[0x27] == CIRRUS_ID_CLGD5436) size = 16 * 1024 * 1024; - else if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) - size = 4 * 1024 * 1024; else + size = 4 * 1024 * 1024; } else { /*VLB*/ base = 128*1024*1024; if (svga->crtc[0x27] == CIRRUS_ID_CLGD5436) From 3351d311cd6d675f9c02f4b8dd7d0f74fa3f89d6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 2 Mar 2018 01:15:55 +0100 Subject: [PATCH 8/9] Updated ROM set link in README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5aada5fa1..66aa93238 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ guide: 7. In order to test your fresh build, replace the `86Box.exe` in your current 86Box enviroment with your freshly built one. If you do not have a pre-existing 86Box environment, download the latest successful build from - http://ci.86box.net, and the ROM set from http://tinyurl.com/rs20171231. + http://ci.86box.net, and the ROM set from http://tinyurl.com/rs20180302. 8. Enjoy using and testing the emulator! :) If you encounter issues at any step or have additional questions, please join From 22e1b2f83aa407f93c62a8223aba087f7c76bfe0 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 2 Mar 2018 18:33:22 +0100 Subject: [PATCH 9/9] Added ATI Korean VGA, based on PCem patch from greatpsycho. --- src/rom.c | 3 +- src/video/vid_ati28800.c | 159 +++++++++++++++++++++++++++++++++++- src/video/vid_ati28800.h | 1 + src/video/vid_svga.c | 6 +- src/video/vid_svga_render.c | 104 +++++++++++++++++++---- src/video/video.c | 13 ++- src/video/video.h | 7 +- 7 files changed, 270 insertions(+), 23 deletions(-) diff --git a/src/rom.c b/src/rom.c index 62ee88733..298f11af5 100644 --- a/src/rom.c +++ b/src/rom.c @@ -13,7 +13,7 @@ * - c386sx16 BIOS fails checksum * - the loadfont() calls should be done elsewhere * - * Version: @(#)rom.c 1.0.29 2018/02/05 + * Version: @(#)rom.c 1.0.30 2018/03/02 * * Authors: Sarah Walker, * Miran Grca, @@ -261,6 +261,7 @@ rom_load_bios(int rom_id) loadfont(L"roms/video/mda/mda.rom", 0); loadfont(L"roms/video/wyse700/wy700.rom", 3); loadfont(L"roms/video/genius/8x12.bin", 4); + loadfont(FONT_ATIKOR_PATH, 6); /* If not done yet, allocate a 128KB buffer for the BIOS ROM. */ if (rom == NULL) diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index 2b771a42f..729e7ea6e 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -8,7 +8,7 @@ * * ATI 28800 emulation (VGA Charger) * - * Version: @(#)vid_ati28800.c 1.0.7 2018/02/18 + * Version: @(#)vid_ati28800.c 1.0.8 2018/03/02 * * Authors: Sarah Walker, * Miran Grca, @@ -36,6 +36,8 @@ #include "vid_svga_render.h" +#define BIOS_ATIKOR_PATH L"roms/video/ati28800/atikorvga.bin" + #define BIOS_VGAXL_EVEN_PATH L"roms/video/ati28800/xleven.bin" #define BIOS_VGAXL_ODD_PATH L"roms/video/ati28800/xlodd.bin" @@ -59,6 +61,16 @@ typedef struct ati28800_t } ati28800_t; +uint8_t port_03dd_val; +uint16_t get_korean_font_kind; +int in_get_korean_font_kind_set; +int get_korean_font_enabled; +int get_korean_font_index; +uint16_t get_korean_font_base; +extern int dbcs_mode_enabled; + + + static void ati28800_out(uint16_t addr, uint8_t val, void *p) { ati28800_t *ati28800 = (ati28800_t *)p; @@ -118,6 +130,60 @@ static void ati28800_out(uint16_t addr, uint8_t val, void *p) svga_out(addr, val, svga); } +void ati28800k_out(uint16_t addr, uint8_t val, void *p) +{ + ati28800_t *ati28800 = (ati28800_t *)p; + svga_t *svga = &ati28800->svga; + uint16_t oldaddr = addr; + + if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) + addr ^= 0x60; + + switch (addr) + { + case 0x1CF: + if(ati28800->index == 0xBF && ((ati28800->regs[0xBF] ^ val) & 0x20)) + { + dbcs_mode_enabled = val & 0x20; + svga_recalctimings(svga); + + } + ati28800_out(oldaddr, val, p); + break; + case 0x3DD: + port_03dd_val = val; + if(val == 1) get_korean_font_enabled = 0; + if(in_get_korean_font_kind_set) + { + get_korean_font_kind = (val << 8) | (get_korean_font_kind & 0xFF); + get_korean_font_enabled = 1; + get_korean_font_index = 0; + } + break; + case 0x3DE: + in_get_korean_font_kind_set = 0; + switch(port_03dd_val) + { + case 0x10: + get_korean_font_base = ((val & 0x7F) << 7) | (get_korean_font_base & 0x7F); + break; + case 8: + get_korean_font_base = (get_korean_font_base & 0x3F80) | (val & 0x7F); + break; + case 1: + get_korean_font_kind = (get_korean_font_kind & 0xFF00) | val; + if(val & 2) in_get_korean_font_kind_set = 1; + break; + default: + break; + } + break; + default: + ati28800_out(oldaddr, val, p); + break; + } +} + static uint8_t ati28800_in(uint16_t addr, void *p) { ati28800_t *ati28800 = (ati28800_t *)p; @@ -168,6 +234,44 @@ static uint8_t ati28800_in(uint16_t addr, void *p) return temp; } +uint8_t ati28800k_in(uint16_t addr, void *p) +{ + ati28800_t *ati28800 = (ati28800_t *)p; + svga_t *svga = &ati28800->svga; + uint16_t oldaddr = addr; + uint8_t temp = 0xFF; + +// if (addr != 0x3da) pclog("ati28800_in : %04X ", addr); + + if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60; + + switch (addr) + { + case 0x3DE: + if(get_korean_font_enabled && (ati28800->regs[0xBF] & 0x20)) + { + switch(get_korean_font_kind >> 8) + { + case 4: /* ROM font */ + temp = fontdatksc5601[get_korean_font_base][get_korean_font_index++]; + break; + case 2: /* User defined font - TODO : Should be implemented later */ + temp = 0; + break; + default: + break; + } + get_korean_font_index &= 0x1F; + } + break; + default: + temp = ati28800_in(oldaddr, p); + break; + } + if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,cpu_state.pc); + return temp; +} + static void ati28800_recalctimings(svga_t *svga) { ati28800_t *ati28800 = (ati28800_t *)svga->p; @@ -181,6 +285,39 @@ static void ati28800_recalctimings(svga_t *svga) } } +void * +ati28800k_init(device_t *info) +{ + ati28800_t *ati28800 = malloc(sizeof(ati28800_t)); + memset(ati28800, 0, sizeof(ati28800_t)); + + + port_03dd_val = 0; + get_korean_font_base = 0; + get_korean_font_index = 0; + get_korean_font_enabled = 0; + get_korean_font_kind = 0; + in_get_korean_font_kind_set = 0; + dbcs_mode_enabled = 0; + + rom_init(&ati28800->bios_rom, BIOS_ATIKOR_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + svga_init(&ati28800->svga, ati28800, 1 << 19, /*512kb*/ + ati28800_recalctimings, + ati28800k_in, ati28800k_out, + NULL, + NULL); + + io_sethandler(0x01ce, 0x0002, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800); + io_sethandler(0x03c0, 0x0020, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800); + + ati28800->svga.miscout = 1; + + ati_eeprom_load(&ati28800->eeprom, L"atikorvga.nvr", 0); + + return ati28800; +} + static void * ati28800_init(device_t *info) { @@ -250,6 +387,13 @@ ati28800_available(void) } +static int +ati28800k_available() +{ + return ((rom_present(BIOS_ATIKOR_PATH) && rom_present(FONT_ATIKOR_PATH))); +} + + static int compaq_ati28800_available(void) { @@ -362,6 +506,19 @@ device_t ati28800_device = ati28800_config }; +device_t ati28800k_device = +{ + "ATI Korean VGA", + DEVICE_ISA, + 0, + ati28800k_init, ati28800_close, NULL, + ati28800k_available, + ati28800_speed_changed, + ati28800_force_redraw, + ati28800_add_status_info, + ati28800_config +}; + device_t compaq_ati28800_device = { "Compaq ATI-28800", diff --git a/src/video/vid_ati28800.h b/src/video/vid_ati28800.h index b30631eaa..70535331a 100644 --- a/src/video/vid_ati28800.h +++ b/src/video/vid_ati28800.h @@ -2,6 +2,7 @@ see COPYING for more details */ extern device_t ati28800_device; +extern device_t ati28800k_device; extern device_t compaq_ati28800_device; #if defined(DEV_BRANCH) && defined(USE_XL24) extern device_t ati28800_wonderxl24_device; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 24459ea29..d17a3aae0 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -11,7 +11,7 @@ * This is intended to be used by another SVGA driver, * and not as a card in it's own right. * - * Version: @(#)vid_svga.c 1.0.22 2018/03/01 + * Version: @(#)vid_svga.c 1.0.23 2018/03/02 * * Authors: Sarah Walker, * Miran Grca, @@ -409,7 +409,7 @@ void svga_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp; svga->render = svga_render_blank; if (!svga->scrblank && svga->attr_palette_enable) { - if (!(svga->gdcreg[6] & 1)) /*Text mode*/ { + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ if (svga->seqregs[1] & 8) /*40 column*/ { svga->render = svga_render_text_40; svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; @@ -666,7 +666,7 @@ void svga_poll(void *p) svga->video_res_x = wx; svga->video_res_y = wy + 1; - if (!(svga->gdcreg[6] & 1)) { /*Text mode*/ + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ svga->video_res_x /= (svga->seqregs[1] & 1) ? 8 : 9; svga->video_res_y /= (svga->crtc[9] & 31) + 1; svga->video_bpp = 0; diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index 587a5138b..3467c024e 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -8,7 +8,7 @@ * * SVGA renderers. * - * Version: @(#)vid_svga_render.c 1.0.5 2018/02/08 + * Version: @(#)vid_svga_render.c 1.0.6 2018/03/02 * * Authors: Sarah Walker, * Miran Grca, @@ -92,6 +92,9 @@ uint32_t shade[5][256] = } }; +int dbcs_mode_enabled = 0; + + void svga_render_blank(svga_t *svga) { int x, xx; @@ -205,7 +208,7 @@ void svga_render_text_80(svga_t *svga) uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[32 + x_add]; int x, xx; int drawcursor; - uint8_t chr, attr, dat; + uint8_t chr, attr, dat, nextchr; uint32_t charaddr; int fg, bg; int xinc = (svga->seqregs[1] & 1) ? 8 : 9; @@ -215,6 +218,85 @@ void svga_render_text_80(svga_t *svga) drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + + + if(dbcs_mode_enabled && x + xinc < svga->hdisp && chr & 0x80) + { + nextchr = svga->vram[((svga->ma + 4) << 1) & svga->vram_display_mask]; + if(nextchr & 0x80) + { + if (drawcursor) + { + bg = svga->pallook[svga->egapal[attr & 15]]; + fg = svga->pallook[svga->egapal[attr >> 4]]; + } + else + { + fg = svga->pallook[svga->egapal[attr & 15]]; + bg = svga->pallook[svga->egapal[attr >> 4]]; + if (attr & 0x80 && svga->attrregs[0x10] & 8) + { + bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + if (svga->blink & 16) + fg = bg; + } + } + + dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)][svga->sc]; + if (svga->seqregs[1] & 1) + { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + } + else + { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4)) + p[8] = bg; + else + p[8] = (dat & 1) ? fg : bg; + } + + attr = svga->vram[(((svga->ma + 4) << 1) + 1) & svga->vram_display_mask]; + if (drawcursor) + { + bg = svga->pallook[svga->egapal[attr & 15]]; + fg = svga->pallook[svga->egapal[attr >> 4]]; + } + else + { + fg = svga->pallook[svga->egapal[attr & 15]]; + bg = svga->pallook[svga->egapal[attr >> 4]]; + if (attr & 0x80 && svga->attrregs[0x10] & 8) + { + bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + if (svga->blink & 16) + fg = bg; + } + } + + dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)][svga->sc + 16]; + if (svga->seqregs[1] & 1) + { + for (xx = 0; xx < 8; xx++) + p[xx+8] = (dat & (0x80 >> xx)) ? fg : bg; + } + else + { + for (xx = 0; xx < 8; xx++) + p[xx+9] = (dat & (0x80 >> xx)) ? fg : bg; + if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4)) + p[17] = bg; + else + p[17] = (dat & 1) ? fg : bg; + } + svga->ma += 8; + p += xinc * 2; + continue; + } + } + if (attr & 8) charaddr = svga->charsetb + (chr * 128); else charaddr = svga->charseta + (chr * 128); @@ -339,16 +421,8 @@ void svga_render_2bpp_highres(svga_t *svga) { uint8_t dat[2]; - if (svga->sc & 1 && !(svga->crtc[0x17] & 1)) - { - dat[0] = svga->vram[(svga->ma << 1) + 0x8000]; - dat[1] = svga->vram[(svga->ma << 1) + 0x8001]; - } - else - { - dat[0] = svga->vram[(svga->ma << 1)]; - dat[1] = svga->vram[(svga->ma << 1) + 1]; - } + dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & 3) & (~svga->crtc[0x17] & 3)) * 0x8000]; + dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & 3) & (~svga->crtc[0x17] & 3)) * 0x8000 + 1]; svga->ma += 4; svga->ma &= svga->vram_display_mask; @@ -435,10 +509,8 @@ void svga_render_4bpp_highres(svga_t *svga) uint8_t edat[4]; uint8_t dat; - if (svga->sc & 1 && !(svga->crtc[0x17] & 1)) - *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma | 0x8000]); - else - *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma]); + *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma | ((svga->sc & 3) & (~svga->crtc[0x17] & 3)) * 0x8000]); + svga->ma += 4; svga->ma &= svga->vram_display_mask; diff --git a/src/video/video.c b/src/video/video.c index 0c73de294..5b46a4c72 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -40,7 +40,7 @@ * W = 3 bus clocks * L = 4 bus clocks * - * Version: @(#)video.c 1.0.16 2018/02/24 + * Version: @(#)video.c 1.0.17 2018/03/02 * * Authors: Sarah Walker, * Miran Grca, @@ -79,6 +79,7 @@ uint8_t fontdat[2048][8]; /* IBM CGA font */ uint8_t fontdatm[2048][16]; /* IBM MDA font */ uint8_t fontdatw[512][32]; /* Wyse700 font */ uint8_t fontdat8x12[256][16]; /* MDSI Genius font */ +uint8_t fontdatksc5601[16384][32]; /* Korean KSC-5601 font */ uint32_t pal_lookup[256]; int xsize = 1, ysize = 1; @@ -757,6 +758,16 @@ loadfont(wchar_t *s, int format) } } break; + + case 6: /* Korean KSC-5601 */ + for (c=0;c<16384;c++) + { + for (d=0;d<32;d++) + { + fontdatksc5601[c][d]=getc(f); + } + } + break; } (void)fclose(f); diff --git a/src/video/video.h b/src/video/video.h index 1a03361d6..7b2fadd1a 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -8,7 +8,7 @@ * * Definitions for the video controller module. * - * Version: @(#)video.h 1.0.21 2018/02/25 + * Version: @(#)video.h 1.0.22 2018/03/02 * * Authors: Sarah Walker, * Miran Grca, @@ -22,6 +22,9 @@ # define EMU_VIDEO_H +#define FONT_ATIKOR_PATH L"roms/video/ati28800/ati_ksc5601.rom" + + #define makecol(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) #define makecol32(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) @@ -58,6 +61,7 @@ enum { GFX_TGUI9400CXI, /* Trident TGUI9400CXi VLB */ GFX_TGUI9440_VLB, /* Trident TGUI9440AGi VLB */ GFX_TGUI9440_PCI, /* Trident TGUI9440AGi PCI */ + GFX_ATIKOREANVGA, /*ATI Korean VGA (28800-5)*/ GFX_VGA88, /* ATI VGA-88 (18800-1) */ GFX_VGAEDGE16, /* ATI VGA Edge-16 (18800-1) */ GFX_VGACHARGER, /* ATI VGA Charger (28800-5) */ @@ -166,6 +170,7 @@ extern int video_fullscreen, extern int fullchange; extern uint8_t fontdat[2048][8]; extern uint8_t fontdatm[2048][16]; +extern uint8_t fontdatksc5601[16384][32]; extern uint32_t *video_6to8, *video_15to32, *video_16to32;