diff --git a/src/chipset/headland.c b/src/chipset/headland.c index 1c122e126..337aefb00 100644 --- a/src/chipset/headland.c +++ b/src/chipset/headland.c @@ -18,11 +18,17 @@ * Copyright 2017-2019 Miran Grca. * Copyright 2017-2019 GreatPsycho. */ +#ifdef ENABLE_HEADLAND_LOG +#include +#endif #include #include #include #include #include +#ifdef ENABLE_HEADLAND_LOG +#define HAVE_STDARG_H +#endif #include <86box/86box.h> #include "cpu.h" #include "x86.h" @@ -35,6 +41,24 @@ #include <86box/plat_unused.h> #include <86box/port_92.h> #include <86box/chipset.h> +#include <86box/log.h> + +#ifdef ENABLE_HEADLAND_LOG +int headland_do_log = ENABLE_HEADLAND_LOG; + +static void +headland_log(void *priv, const char *fmt, ...) +{ + if (headland_do_log) { + va_list ap; + va_start(ap, fmt); + log_out(priv, fmt, ap); + va_end(ap); + } +} +#else +# define headland_log(fmt, ...) +#endif enum { HEADLAND_GC103 = 0x00, @@ -82,6 +106,8 @@ typedef struct headland_t { mem_mapping_t high_mapping; mem_mapping_t shadow_mapping[2]; mem_mapping_t upper_mapping[24]; + + void * log; /* New logging system */ } headland_t; /* TODO - Headland chipset's memory address mapping emulation isn't fully implemented yet, @@ -117,27 +143,30 @@ get_addr(headland_t *dev, uint32_t addr, headland_mr_t *mr) else if ((addr >= 0xfe0000) && (addr <= 0xffffff)) return addr & 0x0fffff; - if (dev->revision == 8) { - shift = (dev->cr[0] & 0x80) ? 21 : ((dev->cr[6] & 0x01) ? 23 : 19); - other_shift = (dev->cr[0] & 0x80) ? ((dev->cr[6] & 0x01) ? 19 : 23) : 21; + if ((dev->revision == 8) && ((dev->cr[6] & 0x01) == 0x01)) { + shift = (dev->cr[0] & 0x80) ? 21 : ((dev->cr[1] & 0x40) ? 19 : 23); + other_shift = (dev->cr[0] & 0x80) ? 23 : ((dev->cr[1] & 0x40) ? 23 : 23); } else { shift = (dev->cr[0] & 0x80) ? 21 : 19; - other_shift = (dev->cr[0] & 0x80) ? 21 : 19; + other_shift = (dev->cr[0] & 0x80) ? 19 : 21; } + headland_log(dev->log, "Headland shift values: shift = %i, other_shift = %i\n", shift, other_shift); + /* Bank size = 1 << (bank shift + 2) . */ bank_shift[0] = bank_shift[1] = shift; bank_base[0] = 0x00000000; bank_base[1] = bank_base[0] + (1 << shift); - bank_base[2] = bank_base[1] + (1 << shift); - if ((dev->revision > 0) && (dev->revision < 8) && (dev->cr[1] & 0x40)) { + if ((dev->revision > 0) && (dev->cr[1] & 0x40)) { bank_shift[2] = bank_shift[3] = other_shift; + bank_base[2] = bank_base[1] + (1 << other_shift); bank_base[3] = bank_base[2] + (1 << other_shift); /* First address after the memory is bank_base[3] + (1 << other_shift) */ } else { bank_shift[2] = bank_shift[3] = shift; + bank_base[2] = bank_base[1] + (1 << shift); bank_base[3] = bank_base[2] + (1 << shift); /* First address after the memory is bank_base[3] + (1 << shift) */ } @@ -248,15 +277,18 @@ memmap_state_update(headland_t *dev) memmap_state_default(dev, ht_romcs); + headland_log(dev->log, "Headland 384K Remap %sabled\n", ht_cr0 & 0x04 ? "Dis" : "En"); if (mem_size > 640) { if (ht_cr0 & 0x04) { mem_mapping_set_addr(&dev->mid_mapping, 0xA0000, 0x40000); mem_mapping_set_exec(&dev->mid_mapping, ram + 0xA0000); mem_mapping_disable(&dev->mid_mapping); if (mem_size > 1024) { - mem_set_mem_state((mem_size << 10), 0x60000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_set_mem_state((mem_size << 10), 0x60000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); mem_mapping_set_addr(&dev->high_mapping, 0x100000, (mem_size - 1024) << 10); mem_mapping_set_exec(&dev->high_mapping, ram + 0x100000); + } else if ((mem_size > 640) && (mem_size <=1024)) { + mem_set_mem_state(0x100000, (mem_size - 640) << 10, MEM_READ_EXTANY | MEM_WRITE_EXTANY); } } else { /* 1 MB - 1 MB + 384k: RAM pointing to A0000-FFFFF @@ -266,14 +298,17 @@ memmap_state_update(headland_t *dev) mem_mapping_set_exec(&dev->mid_mapping, ram + 0xA0000); if (mem_size > 1024) { /* We have ram above 1 MB, we need to relocate that. */ - mem_set_mem_state((mem_size << 10), 0x60000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + mem_set_mem_state((mem_size << 10), 0x60000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); mem_mapping_set_addr(&dev->high_mapping, 0x160000, (mem_size - 1024) << 10); mem_mapping_set_exec(&dev->high_mapping, ram + 0x100000); + } else if ((mem_size > 640) && (mem_size <=1024)) { + mem_set_mem_state(0x100000, (mem_size - 640) << 10, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); } } } - switch (ht_cr0) { + headland_log(dev->log, "Headland shadow RAM val = %02X\n", ht_cr0 & 0x18); + switch (ht_cr0 & 0x18) { case 0x18: if ((mem_size << 10) > 0xe0000) { mem_set_mem_state(0x0e0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); @@ -331,6 +366,8 @@ hl_write(uint16_t addr, uint8_t val, void *priv) { headland_t *dev = (headland_t *) priv; + headland_log(dev->log, "[%04X:%08X] Headland: [W] addr = %04X, val = %02X\n", CS, cpu_state.pc, addr, val); + switch (addr) { case 0x01ec: dev->ems_mr[dev->ems_mar & 0x3f].mr = val | 0xff00; @@ -401,6 +438,8 @@ hl_writew(uint16_t addr, uint16_t val, void *priv) { headland_t *dev = (headland_t *) priv; + headland_log(dev->log, "[%04X:%08X] Headland: [W] addr = %04X, val = %04X\n", CS, cpu_state.pc, addr, val); + switch (addr) { case 0x01ec: dev->ems_mr[dev->ems_mar & 0x3f].mr = val; @@ -470,6 +509,8 @@ hl_read(uint16_t addr, void *priv) break; } + headland_log(dev->log, "[%04X:%08X] Headland [R] addr = %04X, val = %02X\n", CS, cpu_state.pc, addr, ret); + return ret; } @@ -490,6 +531,8 @@ hl_readw(uint16_t addr, void *priv) break; } + headland_log(dev->log, "[%04X:%08X] Headland [R] addr = %04X, val = %04X\n", CS, cpu_state.pc, addr, ret); + return ret; } @@ -584,6 +627,11 @@ headland_close(void *priv) { headland_t *dev = (headland_t *) priv; + if (dev->log != NULL) { + log_close(dev->log); + dev->log = NULL; + } + free(dev); } @@ -621,6 +669,8 @@ headland_init(const device_t *info) dev->ems_mr[i].headland = dev; } + dev->log = log_open("Headland"); + /* Turn off mem.c mappings. */ mem_mapping_disable(&ram_low_mapping); mem_mapping_disable(&ram_mid_mapping); diff --git a/src/config.c b/src/config.c index 06049713c..edd713755 100644 --- a/src/config.c +++ b/src/config.c @@ -910,10 +910,10 @@ load_network(void) nc->slirp_net[0] = '\0'; } - sprintf(temp, "net_%02i_switch_group", c + 1); - nc->switch_group = ini_section_get_int(cat, temp, NET_SWITCH_GRP_MIN); - if (nc->switch_group < NET_SWITCH_GRP_MIN) - nc->switch_group = NET_SWITCH_GRP_MIN; + sprintf(temp, "net_%02i_secret", c + 1); + p = ini_section_get_string(cat, temp, NULL); + strncpy(nc->secret, p ? p : "", sizeof(nc->secret) - 1); + nc->secret[sizeof(net_cards_conf[c].secret) - 1] = '\0'; sprintf(temp, "net_%02i_promisc", c + 1); nc->promisc_mode = ini_section_get_int(cat, temp, 0); @@ -3019,11 +3019,11 @@ save_network(void) ini_section_delete_var(cat, temp); } - sprintf(temp, "net_%02i_switch_group", c + 1); - if (nc->switch_group == NET_SWITCH_GRP_MIN) + sprintf(temp, "net_%02i_secret", c + 1); + if (nc->secret[0] == '\0') ini_section_delete_var(cat, temp); else - ini_section_set_int(cat, temp, nc->switch_group); + ini_section_set_string(cat, temp, net_cards_conf[c].secret); sprintf(temp, "net_%02i_promisc", c + 1); if (nc->promisc_mode == 0) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 21f06df03..8a959684e 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -4758,7 +4758,7 @@ static const scancode scancode_set82[512] = { // clang-format on }; /* Scancode set 8Ah : IBM 5556 keyboard compatible scancode set used by J-DOS */ -static scancode scancode_set8a[512] = +const scancode scancode_set8a[512] = { // clang-format off {.mk = { 0 }, .brk = { 0 } }, /* 000 */ @@ -4817,7 +4817,7 @@ static scancode scancode_set8a[512] = {.mk = { 0x0a, 0 }, .brk = { 0 } }, /* 035 */ {.mk = { 0x39, 0 }, .brk = { 0xb9, 0 } }, /* 036 RSHIFT */ {.mk = { 0x64, 0 }, .brk = { 0 } }, /* 037 * (asterisk) */ - {.mk = { 0x3A, 0 }, .brk = { 0xba, 0 } }, /* 038 0x3A LALT = Kanji */ + {.mk = { 0x3a, 0 }, .brk = { 0xba, 0 } }, /* 038 0x3A LALT = Kanji */ {.mk = { 0x34, 0 }, .brk = { 0 } }, /* 039 */ {.mk = { 0x32, 0 }, .brk = { 0xb2, 0 } }, /* 03a CAPSLOCK */ {.mk = { 0x68, 0 }, .brk = { 0 } }, /* 03b F1 */ diff --git a/src/device/postcard.c b/src/device/postcard.c index f33574452..f842cbb33 100644 --- a/src/device/postcard.c +++ b/src/device/postcard.c @@ -195,6 +195,8 @@ postcard_init(UNUSED(const device_t *info)) postcard_port = 0x190; /* ISA PS/2 machines */ else if (strstr(machines[machine].name, " IBM XT ")) postcard_port = 0x60; /* IBM XT */ + else if (strstr(machines[machine].name, " Multistation ")) + postcard_port = 0xA1; /* IBM 5550 */ else if (strstr(machines[machine].name, " IBM PCjr")) { postcard_port = 0x10; /* IBM PCjr */ postcard_ports_num = 3; /* IBM PCjr error ports 11h and 12h */ diff --git a/src/dma.c b/src/dma.c index 5dfd70ae8..e36b0b4e5 100644 --- a/src/dma.c +++ b/src/dma.c @@ -978,10 +978,15 @@ dma_page_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) addr &= 0x0f; dmaregs[2][addr] = val; - if (addr >= 8) - addr = convert[addr & 0x07] | 4; - else - addr = convert[addr & 0x07]; + if (machines[machine].init == machine_xt_ibm5550_init) { + if (addr >= 4) + addr = 8; + } else { + if (addr >= 8) + addr = convert[addr & 0x07] | 4; + else + addr = convert[addr & 0x07]; + } if (addr < 8) { dma[addr].page_l = val; diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index d6d27da3b..cfc51f2b0 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -664,6 +664,21 @@ real_drive(fdc_t *fdc, int drive) return drive; } +void +fdc_diskchange_interrupt(fdc_t *fdc, int drive) +{ + /* + For the IBM 5550 machine to detect the disk in the drive has been changed. + A hardware interrupt is caused by the FDC (NEC uPD765A) when the Ready line from the drive changes its state. + Other PCs never use the Ready line. + */ + if (fdc->flags & FDC_FLAG_5550) { + fdc->st0 = 0xc0 | (drive & 3); + fdc_int(fdc, 1); + fdd_changed[drive] = 0; + } +} + /* FDD notifies FDC when seek operation is complete */ void fdc_seek_complete_interrupt(fdc_t *fdc, int drive) @@ -822,8 +837,47 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 0: return; case 1: + if (fdc->flags & FDC_FLAG_5550) { + val = 0; + if (!(val & 0x08)) { /* Drive 2 active */ + val = 0x42; + } + if (!(val & 0x04)) { /* Drive 1 active */ + val &= 0xf0; + val |= 0x21; + } + if (!(val & 0x02)) { /* Drive 0 active */ + val &= 0xf0; + val |= 0x10; + } + /* Update the DOR because this emulation module depend on it */ + fdc->dor &= 0x0c; + fdc->dor |= val; + /* We can now simplify this since each motor now spins separately. */ + for (int i = 0; i < FDD_NUM; i++) { + drive_num = real_drive(fdc, i); + if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM)) + val &= ~(0x10 << drive_num); + else + fdd_set_motor_enable(i, (val & (0x10 << drive_num))); + } + drive_num = real_drive(fdc, val & 0x03); + current_drive = drive_num; + fdc->st0 = (fdc->st0 & 0xf8) | (val & 0x03) | (fdd_get_head(drive_num) ? 4 : 0); + fdc_log("val:%x, dor=%x, drv=%x\n", val, fdc->dor, drive_num); + } return; case 2: /*DOR*/ + if (fdc->flags & FDC_FLAG_5550) { /* Reset */ + fdd_stop(fdc->drive); + for (int i = 0; i < FDD_NUM; i++) + fdd_set_motor_enable(i, 0); /* Need to restart fdd timer */ + fdc->stat = 0x00; + fdc->pnum = fdc->ptot = 0; + fdc_soft_reset(fdc); + fdc->dor = 0x0c; + return; + } if (fdc->flags & FDC_FLAG_PCJR) { if ((fdc->dor & 0x40) && !(val & 0x40)) { timer_set_delay_u64(&fdc->watchdog_timer, 1000 * TIMER_USEC); @@ -903,6 +957,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) } return; case 4: /* DSR */ + if (fdc->flags & FDC_FLAG_5550) + picintc(1 << fdc->irq); if (!(fdc->flags & FDC_FLAG_NO_DSR_RESET)) { if (!(val & 0x80)) { timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); @@ -914,6 +970,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->dsr = val; return; case 5: /*Command register*/ + if (fdc->flags & FDC_FLAG_5550) + picintc(1 << fdc->irq); if (fdc->fifointest) { /* Write FIFO buffer in the test mode (PS/55) */ fdc_log("FIFO buffer position = %X\n", ((fifo_t *) fdc->fifo_p)->end); @@ -948,7 +1006,33 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->command = val; fdc->stat |= 0x10; - fdc_log("Starting FDC command %02X\n", fdc->command); + fdc_log("Starting FDC command %02X ", fdc->command); + switch (fdc->command & 0x1f) { + case 0x06: + fdc_log("READ DATA\n"); + break; + case 0x0a: + fdc_log("READ ID\n"); + break; + case 0x07: + fdc_log("RECALIB\n"); + break; + case 0x08: + fdc_log("SENSE INTERRUPT\n"); + break; + case 0x03: + fdc_log("SPECIFY\n"); + break; + case 0x04: + fdc_log("SENSE DRIVE\n"); + break; + case 0x0f: + fdc_log("SEEK\n"); + break; + default: + fdc_log("\n"); + break; + } fdc->error = 0; if (((fdc->command & 0x1f) == 0x02) || ((fdc->command & 0x1f) == 0x05) || @@ -1106,6 +1190,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) if (command_has_drivesel[fdc->command & 0x1F]) { if (fdc->flags & FDC_FLAG_PCJR) fdc->drive = 0; + else if (fdc->flags & FDC_FLAG_5550) + fdc->drive = fdc->params[0] & 3; else fdc->drive = fdc->dor & 3; fdc->rw_drive = fdc->params[0] & 3; @@ -1115,6 +1201,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) } if (fdc->pnum == fdc->ptot) { fdc_log("Got all params %02X\n", fdc->command); + for (int i = 0; i < fdc->ptot; i++) + fdc_log(" [%d] %02x\n", i, fdc->params[i]); fifo_reset(fdc->fifo_p); fdc->interrupt = fdc->processed_cmd; fdc->reset_stat = 0; @@ -1451,6 +1539,8 @@ fdc_read(uint16_t addr, void *priv) ret = 0xc0; ret |= (fdc->dor & 0x01) << 5; /* Drive Select 0 */ ret |= (fdc->dor & 0x30) >> 4; /* Motor Select 1, 0 */ + } else if (fdc->flags & FDC_FLAG_5550) { + ret = 0; } else { if (is486 || !fdc->enable_3f1) ret = 0xff; @@ -1503,9 +1593,13 @@ fdc_read(uint16_t addr, void *priv) ret = (fdc->rwc[drive] << 4) | (fdc->media_id << 6); break; case 4: /*Status*/ + if (fdc->flags & FDC_FLAG_5550) + picintc(1 << fdc->irq); ret = fdc->stat; break; case 5: /*Data*/ + if (fdc->flags & FDC_FLAG_5550) + picintc(1 << fdc->irq); if (fdc->fifointest) { /* Read FIFO buffer in the test mode (PS/55) */ ret = fifo_read(fdc->fifo_p); @@ -1733,6 +1827,8 @@ fdc_callback(void *priv) } if (writeprot[fdc->drive]) fdc->res[10] |= 0x40; + if ((fdc->flags & FDC_FLAG_5550) && drive_empty[fdc->drive])//IBM 5550 + fdc->res[10] &= 0xdf; /* Set Not Ready */ fdc->stat = (fdc->stat & 0xf) | 0xd0; fdc->paramstogo = 1; @@ -2349,6 +2445,10 @@ fdc_set_base(fdc_t *fdc, int base) if (fdc->flags & FDC_FLAG_NSC) { io_sethandler(base + 2, 0x0004, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + } else if (fdc->flags & FDC_FLAG_5550) { + io_sethandler(base, 0x0003, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + io_sethandler(base + 0x0004, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); + io_sethandler(base + 0x0005, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); } else { if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) { io_sethandler(base + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); @@ -2383,6 +2483,10 @@ fdc_remove(fdc_t *fdc) if (fdc->flags & FDC_FLAG_NSC) { io_removehandler(fdc->base_address + 2, 0x0004, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); io_removehandler(fdc->base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + } else if (fdc->flags & FDC_FLAG_5550) { + io_removehandler(fdc->base_address, 0x0003, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); + io_removehandler(fdc->base_address + 4, 0x0001, fdc_read, NULL, NULL, NULL, NULL, NULL, fdc); + io_removehandler(fdc->base_address + 5, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); } else { if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) { io_removehandler(fdc->base_address + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc); @@ -2534,6 +2638,8 @@ fdc_init(const device_t *info) fdc->irq = FDC_TERTIARY_IRQ; else if (fdc->flags & FDC_FLAG_QUA) fdc->irq = FDC_QUATERNARY_IRQ; + else if (fdc->flags & FDC_FLAG_5550) + fdc->irq = 4; else fdc->irq = FDC_PRIMARY_IRQ; @@ -2686,6 +2792,20 @@ const device_t fdc_xt_umc_um8398_device = { .config = NULL }; +const device_t fdc_xt_5550_device = { + .name = "IBM 5550 Floppy Drive Controller", + .internal_name = "fdc_xt_5550", + .flags = 0, + .local = FDC_FLAG_5550, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t fdc_pcjr_device = { .name = "PCjr Floppy Drive Controller", .internal_name = "fdc_pcjr", diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index 89ec2e9f6..592258cee 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -777,6 +777,10 @@ fdd_poll(void *priv) if (!fdd_notfound) fdc_noidam(fdd_fdc); } + + if (fdd_changed[drive]) { + fdc_diskchange_interrupt(fdd_fdc, drive); + } } int diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index ff56aa0ef..e1a818147 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -59,6 +59,7 @@ #define FDC_FLAG_TER 0x40000 /* Is Tertiary */ #define FDC_FLAG_QUA 0x80000 /* Is Quaternary */ #define FDC_FLAG_SMC661 0x100000 /* SM(s)C FDC37C661 - different TDR enhanced mode */ +#define FDC_FLAG_5550 0x200000 /* IBM Multistation 5550 */ typedef struct fdc_t { uint8_t dor; @@ -252,6 +253,7 @@ extern void fdc_reset(void *priv); extern uint8_t fdc_get_current_drive(void); extern void fdc_seek_complete_interrupt(fdc_t *fdc, int drive); +extern void fdc_diskchange_interrupt(fdc_t *fdc, int drive); #ifdef EMU_DEVICE_H extern const device_t fdc_xt_device; @@ -262,6 +264,7 @@ extern const device_t fdc_xt_t1x00_device; extern const device_t fdc_xt_tandy_device; extern const device_t fdc_xt_amstrad_device; extern const device_t fdc_xt_umc_um8398_device; +extern const device_t fdc_xt_5550_device; extern const device_t fdc_pcjr_device; extern const device_t fdc_at_device; extern const device_t fdc_at_sec_device; diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 8b32851bb..16aec312f 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -170,6 +170,7 @@ extern void kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)); extern void kbd_adddata_process_10x(uint16_t val, void (*adddata)(uint16_t val)); extern const scancode scancode_xt[512]; +extern const scancode scancode_set8a[512]; extern uint8_t keyboard_set3_flags[512]; extern uint8_t keyboard_set3_all_repeat; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 824183673..b7702e55b 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -569,6 +569,7 @@ extern int machine_at_acer100t_init(const machine_t *); /* HT18 */ extern int machine_at_ama932j_init(const machine_t *); +extern int machine_at_tandy1000rsx_init(const machine_t *); /* Intel 82335 */ extern int machine_at_adi386sx_init(const machine_t *); @@ -1511,6 +1512,10 @@ extern int machine_xt_iskra3104_init(const machine_t *); extern int machine_xt_lxt3_init(const machine_t *); extern int machine_xt_compaq_deskpro_init(const machine_t *); +/* m_xt_ibm5550.c */ + +extern int machine_xt_ibm5550_init(const machine_t *); + /* m_xt_t1000.c */ #ifdef EMU_DEVICE_H extern const device_t t1000_video_device; diff --git a/src/include/86box/network.h b/src/include/86box/network.h index f3f1b1f8a..d208cd345 100644 --- a/src/include/86box/network.h +++ b/src/include/86box/network.h @@ -60,8 +60,6 @@ #define NET_QUEUE_COUNT 4 #define NET_CARD_MAX 4 #define NET_HOST_INTF_MAX 64 -#define NET_SWITCH_GRP_MIN 1 -#define NET_SWITCH_GRP_MAX 10 #define NET_PERIOD_10M 0.8 #define NET_PERIOD_100M 0.08 @@ -97,7 +95,7 @@ typedef struct netcard_conf_t { int net_type; char host_dev_name[128]; uint32_t link_state; - uint8_t switch_group; + char secret[256]; uint8_t promisc_mode; char slirp_net[16]; char nrs_hostname[128]; diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index 991be4424..bc346f549 100644 --- a/src/include/86box/pit.h +++ b/src/include/86box/pit.h @@ -90,6 +90,8 @@ typedef struct pit_intf_t { void (*write)(uint16_t addr, uint8_t val, void *priv); /* Gets a counter's count. */ uint16_t (*get_count)(void *data, int counter_id); + /* Gets a counter's out. */ + int (*get_outlevel)(void *data, int counter_id); /* Sets a counter's GATE input. */ void (*set_gate)(void *data, int counter_id, int gate); /* Sets if a counter's CLOCK input is from the timer or not - used by PCjr. */ diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index 71cd65e5a..5cf11bc3c 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -245,6 +245,7 @@ extern const device_t soundman_device; /* Tandy PSSJ */ extern const device_t pssj_device; extern const device_t pssj_isa_device; +extern const device_t pssj_1e0_device; /* Tandy PSG */ extern const device_t tndy_device; diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 252463af7..3d6bf3caf 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -352,8 +352,9 @@ extern void ati8514_out(uint16_t addr, uint8_t val, void *priv); extern uint8_t ati8514_in(uint16_t addr, void *priv); extern void ati8514_recalctimings(svga_t *svga); extern uint8_t ati8514_mca_read(int port, void *priv); -extern uint8_t ati8514_rom_readb(uint32_t addr, void *priv); -extern uint16_t ati8514_rom_readw(uint32_t addr, void *priv); +extern uint8_t ati8514_bios_rom_readb(uint32_t addr, void *priv); +extern uint16_t ati8514_bios_rom_readw(uint32_t addr, void *priv); +extern uint32_t ati8514_bios_rom_readl(uint32_t addr, void *priv); extern void ati8514_mca_write(int port, uint8_t val, void *priv); extern void ati8514_pos_write(uint16_t port, uint8_t val, void *priv); extern void ati8514_init(svga_t *svga, void *ext8514, void *dev8514); diff --git a/src/include/shathree.h b/src/include/shathree.h new file mode 100644 index 000000000..98e804b33 --- /dev/null +++ b/src/include/shathree.h @@ -0,0 +1,481 @@ +/* +** This code is from SQLite +** (https://sqlite.org/src/info/2025-02-27T21:17:55z), at file path +** ext/misc/shathree.c. The SQLite functions have been removed, but +** it is the same code written by D. Richard Hipp. +*/ + +#ifndef SHATHREE_H + +/* +** 2017-03-08 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +*/ +#include +#include +#include + +/****************************************************************************** +** The Hash Engine +*/ +/* +** Macros to determine whether the machine is big or little endian, +** and whether or not that determination is run-time or compile-time. +** +** For best performance, an attempt is made to guess at the byte-order +** using C-preprocessor macros. If that is unsuccessful, or if +** -DSHA3_BYTEORDER=0 is set, then byte-order is determined +** at run-time. +*/ +#ifndef SHA3_BYTEORDER +# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ + defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ + defined(__arm__) +# define SHA3_BYTEORDER 1234 +# elif defined(sparc) || defined(__ppc__) +# define SHA3_BYTEORDER 4321 +# else +# define SHA3_BYTEORDER 0 +# endif +#endif + +#define u64 uint64_t + + +/* +** State structure for a SHA3 hash in progress +*/ +typedef struct SHA3Context SHA3Context; +struct SHA3Context { + union { + u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */ + unsigned char x[1600]; /* ... or 1600 bytes */ + } u; + unsigned nRate; /* Bytes of input accepted per Keccak iteration */ + unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */ + unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */ + unsigned iSize; /* 224, 256, 358, or 512 */ +}; + +/* +** A single step of the Keccak mixing function for a 1600-bit state +*/ +static void KeccakF1600Step(SHA3Context *p){ + int i; + u64 b0, b1, b2, b3, b4; + u64 c0, c1, c2, c3, c4; + u64 d0, d1, d2, d3, d4; + static const u64 RC[] = { + 0x0000000000000001ULL, 0x0000000000008082ULL, + 0x800000000000808aULL, 0x8000000080008000ULL, + 0x000000000000808bULL, 0x0000000080000001ULL, + 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x000000000000008aULL, 0x0000000000000088ULL, + 0x0000000080008009ULL, 0x000000008000000aULL, + 0x000000008000808bULL, 0x800000000000008bULL, + 0x8000000000008089ULL, 0x8000000000008003ULL, + 0x8000000000008002ULL, 0x8000000000000080ULL, + 0x000000000000800aULL, 0x800000008000000aULL, + 0x8000000080008081ULL, 0x8000000000008080ULL, + 0x0000000080000001ULL, 0x8000000080008008ULL + }; +# define a00 (p->u.s[0]) +# define a01 (p->u.s[1]) +# define a02 (p->u.s[2]) +# define a03 (p->u.s[3]) +# define a04 (p->u.s[4]) +# define a10 (p->u.s[5]) +# define a11 (p->u.s[6]) +# define a12 (p->u.s[7]) +# define a13 (p->u.s[8]) +# define a14 (p->u.s[9]) +# define a20 (p->u.s[10]) +# define a21 (p->u.s[11]) +# define a22 (p->u.s[12]) +# define a23 (p->u.s[13]) +# define a24 (p->u.s[14]) +# define a30 (p->u.s[15]) +# define a31 (p->u.s[16]) +# define a32 (p->u.s[17]) +# define a33 (p->u.s[18]) +# define a34 (p->u.s[19]) +# define a40 (p->u.s[20]) +# define a41 (p->u.s[21]) +# define a42 (p->u.s[22]) +# define a43 (p->u.s[23]) +# define a44 (p->u.s[24]) +# define ROL64(a,x) ((a<>(64-x))) + + for(i=0; i<24; i+=4){ + c0 = a00^a10^a20^a30^a40; + c1 = a01^a11^a21^a31^a41; + c2 = a02^a12^a22^a32^a42; + c3 = a03^a13^a23^a33^a43; + c4 = a04^a14^a24^a34^a44; + d0 = c4^ROL64(c1, 1); + d1 = c0^ROL64(c2, 1); + d2 = c1^ROL64(c3, 1); + d3 = c2^ROL64(c4, 1); + d4 = c3^ROL64(c0, 1); + + b0 = (a00^d0); + b1 = ROL64((a11^d1), 44); + b2 = ROL64((a22^d2), 43); + b3 = ROL64((a33^d3), 21); + b4 = ROL64((a44^d4), 14); + a00 = b0 ^((~b1)& b2 ); + a00 ^= RC[i]; + a11 = b1 ^((~b2)& b3 ); + a22 = b2 ^((~b3)& b4 ); + a33 = b3 ^((~b4)& b0 ); + a44 = b4 ^((~b0)& b1 ); + + b2 = ROL64((a20^d0), 3); + b3 = ROL64((a31^d1), 45); + b4 = ROL64((a42^d2), 61); + b0 = ROL64((a03^d3), 28); + b1 = ROL64((a14^d4), 20); + a20 = b0 ^((~b1)& b2 ); + a31 = b1 ^((~b2)& b3 ); + a42 = b2 ^((~b3)& b4 ); + a03 = b3 ^((~b4)& b0 ); + a14 = b4 ^((~b0)& b1 ); + + b4 = ROL64((a40^d0), 18); + b0 = ROL64((a01^d1), 1); + b1 = ROL64((a12^d2), 6); + b2 = ROL64((a23^d3), 25); + b3 = ROL64((a34^d4), 8); + a40 = b0 ^((~b1)& b2 ); + a01 = b1 ^((~b2)& b3 ); + a12 = b2 ^((~b3)& b4 ); + a23 = b3 ^((~b4)& b0 ); + a34 = b4 ^((~b0)& b1 ); + + b1 = ROL64((a10^d0), 36); + b2 = ROL64((a21^d1), 10); + b3 = ROL64((a32^d2), 15); + b4 = ROL64((a43^d3), 56); + b0 = ROL64((a04^d4), 27); + a10 = b0 ^((~b1)& b2 ); + a21 = b1 ^((~b2)& b3 ); + a32 = b2 ^((~b3)& b4 ); + a43 = b3 ^((~b4)& b0 ); + a04 = b4 ^((~b0)& b1 ); + + b3 = ROL64((a30^d0), 41); + b4 = ROL64((a41^d1), 2); + b0 = ROL64((a02^d2), 62); + b1 = ROL64((a13^d3), 55); + b2 = ROL64((a24^d4), 39); + a30 = b0 ^((~b1)& b2 ); + a41 = b1 ^((~b2)& b3 ); + a02 = b2 ^((~b3)& b4 ); + a13 = b3 ^((~b4)& b0 ); + a24 = b4 ^((~b0)& b1 ); + + c0 = a00^a20^a40^a10^a30; + c1 = a11^a31^a01^a21^a41; + c2 = a22^a42^a12^a32^a02; + c3 = a33^a03^a23^a43^a13; + c4 = a44^a14^a34^a04^a24; + d0 = c4^ROL64(c1, 1); + d1 = c0^ROL64(c2, 1); + d2 = c1^ROL64(c3, 1); + d3 = c2^ROL64(c4, 1); + d4 = c3^ROL64(c0, 1); + + b0 = (a00^d0); + b1 = ROL64((a31^d1), 44); + b2 = ROL64((a12^d2), 43); + b3 = ROL64((a43^d3), 21); + b4 = ROL64((a24^d4), 14); + a00 = b0 ^((~b1)& b2 ); + a00 ^= RC[i+1]; + a31 = b1 ^((~b2)& b3 ); + a12 = b2 ^((~b3)& b4 ); + a43 = b3 ^((~b4)& b0 ); + a24 = b4 ^((~b0)& b1 ); + + b2 = ROL64((a40^d0), 3); + b3 = ROL64((a21^d1), 45); + b4 = ROL64((a02^d2), 61); + b0 = ROL64((a33^d3), 28); + b1 = ROL64((a14^d4), 20); + a40 = b0 ^((~b1)& b2 ); + a21 = b1 ^((~b2)& b3 ); + a02 = b2 ^((~b3)& b4 ); + a33 = b3 ^((~b4)& b0 ); + a14 = b4 ^((~b0)& b1 ); + + b4 = ROL64((a30^d0), 18); + b0 = ROL64((a11^d1), 1); + b1 = ROL64((a42^d2), 6); + b2 = ROL64((a23^d3), 25); + b3 = ROL64((a04^d4), 8); + a30 = b0 ^((~b1)& b2 ); + a11 = b1 ^((~b2)& b3 ); + a42 = b2 ^((~b3)& b4 ); + a23 = b3 ^((~b4)& b0 ); + a04 = b4 ^((~b0)& b1 ); + + b1 = ROL64((a20^d0), 36); + b2 = ROL64((a01^d1), 10); + b3 = ROL64((a32^d2), 15); + b4 = ROL64((a13^d3), 56); + b0 = ROL64((a44^d4), 27); + a20 = b0 ^((~b1)& b2 ); + a01 = b1 ^((~b2)& b3 ); + a32 = b2 ^((~b3)& b4 ); + a13 = b3 ^((~b4)& b0 ); + a44 = b4 ^((~b0)& b1 ); + + b3 = ROL64((a10^d0), 41); + b4 = ROL64((a41^d1), 2); + b0 = ROL64((a22^d2), 62); + b1 = ROL64((a03^d3), 55); + b2 = ROL64((a34^d4), 39); + a10 = b0 ^((~b1)& b2 ); + a41 = b1 ^((~b2)& b3 ); + a22 = b2 ^((~b3)& b4 ); + a03 = b3 ^((~b4)& b0 ); + a34 = b4 ^((~b0)& b1 ); + + c0 = a00^a40^a30^a20^a10; + c1 = a31^a21^a11^a01^a41; + c2 = a12^a02^a42^a32^a22; + c3 = a43^a33^a23^a13^a03; + c4 = a24^a14^a04^a44^a34; + d0 = c4^ROL64(c1, 1); + d1 = c0^ROL64(c2, 1); + d2 = c1^ROL64(c3, 1); + d3 = c2^ROL64(c4, 1); + d4 = c3^ROL64(c0, 1); + + b0 = (a00^d0); + b1 = ROL64((a21^d1), 44); + b2 = ROL64((a42^d2), 43); + b3 = ROL64((a13^d3), 21); + b4 = ROL64((a34^d4), 14); + a00 = b0 ^((~b1)& b2 ); + a00 ^= RC[i+2]; + a21 = b1 ^((~b2)& b3 ); + a42 = b2 ^((~b3)& b4 ); + a13 = b3 ^((~b4)& b0 ); + a34 = b4 ^((~b0)& b1 ); + + b2 = ROL64((a30^d0), 3); + b3 = ROL64((a01^d1), 45); + b4 = ROL64((a22^d2), 61); + b0 = ROL64((a43^d3), 28); + b1 = ROL64((a14^d4), 20); + a30 = b0 ^((~b1)& b2 ); + a01 = b1 ^((~b2)& b3 ); + a22 = b2 ^((~b3)& b4 ); + a43 = b3 ^((~b4)& b0 ); + a14 = b4 ^((~b0)& b1 ); + + b4 = ROL64((a10^d0), 18); + b0 = ROL64((a31^d1), 1); + b1 = ROL64((a02^d2), 6); + b2 = ROL64((a23^d3), 25); + b3 = ROL64((a44^d4), 8); + a10 = b0 ^((~b1)& b2 ); + a31 = b1 ^((~b2)& b3 ); + a02 = b2 ^((~b3)& b4 ); + a23 = b3 ^((~b4)& b0 ); + a44 = b4 ^((~b0)& b1 ); + + b1 = ROL64((a40^d0), 36); + b2 = ROL64((a11^d1), 10); + b3 = ROL64((a32^d2), 15); + b4 = ROL64((a03^d3), 56); + b0 = ROL64((a24^d4), 27); + a40 = b0 ^((~b1)& b2 ); + a11 = b1 ^((~b2)& b3 ); + a32 = b2 ^((~b3)& b4 ); + a03 = b3 ^((~b4)& b0 ); + a24 = b4 ^((~b0)& b1 ); + + b3 = ROL64((a20^d0), 41); + b4 = ROL64((a41^d1), 2); + b0 = ROL64((a12^d2), 62); + b1 = ROL64((a33^d3), 55); + b2 = ROL64((a04^d4), 39); + a20 = b0 ^((~b1)& b2 ); + a41 = b1 ^((~b2)& b3 ); + a12 = b2 ^((~b3)& b4 ); + a33 = b3 ^((~b4)& b0 ); + a04 = b4 ^((~b0)& b1 ); + + c0 = a00^a30^a10^a40^a20; + c1 = a21^a01^a31^a11^a41; + c2 = a42^a22^a02^a32^a12; + c3 = a13^a43^a23^a03^a33; + c4 = a34^a14^a44^a24^a04; + d0 = c4^ROL64(c1, 1); + d1 = c0^ROL64(c2, 1); + d2 = c1^ROL64(c3, 1); + d3 = c2^ROL64(c4, 1); + d4 = c3^ROL64(c0, 1); + + b0 = (a00^d0); + b1 = ROL64((a01^d1), 44); + b2 = ROL64((a02^d2), 43); + b3 = ROL64((a03^d3), 21); + b4 = ROL64((a04^d4), 14); + a00 = b0 ^((~b1)& b2 ); + a00 ^= RC[i+3]; + a01 = b1 ^((~b2)& b3 ); + a02 = b2 ^((~b3)& b4 ); + a03 = b3 ^((~b4)& b0 ); + a04 = b4 ^((~b0)& b1 ); + + b2 = ROL64((a10^d0), 3); + b3 = ROL64((a11^d1), 45); + b4 = ROL64((a12^d2), 61); + b0 = ROL64((a13^d3), 28); + b1 = ROL64((a14^d4), 20); + a10 = b0 ^((~b1)& b2 ); + a11 = b1 ^((~b2)& b3 ); + a12 = b2 ^((~b3)& b4 ); + a13 = b3 ^((~b4)& b0 ); + a14 = b4 ^((~b0)& b1 ); + + b4 = ROL64((a20^d0), 18); + b0 = ROL64((a21^d1), 1); + b1 = ROL64((a22^d2), 6); + b2 = ROL64((a23^d3), 25); + b3 = ROL64((a24^d4), 8); + a20 = b0 ^((~b1)& b2 ); + a21 = b1 ^((~b2)& b3 ); + a22 = b2 ^((~b3)& b4 ); + a23 = b3 ^((~b4)& b0 ); + a24 = b4 ^((~b0)& b1 ); + + b1 = ROL64((a30^d0), 36); + b2 = ROL64((a31^d1), 10); + b3 = ROL64((a32^d2), 15); + b4 = ROL64((a33^d3), 56); + b0 = ROL64((a34^d4), 27); + a30 = b0 ^((~b1)& b2 ); + a31 = b1 ^((~b2)& b3 ); + a32 = b2 ^((~b3)& b4 ); + a33 = b3 ^((~b4)& b0 ); + a34 = b4 ^((~b0)& b1 ); + + b3 = ROL64((a40^d0), 41); + b4 = ROL64((a41^d1), 2); + b0 = ROL64((a42^d2), 62); + b1 = ROL64((a43^d3), 55); + b2 = ROL64((a44^d4), 39); + a40 = b0 ^((~b1)& b2 ); + a41 = b1 ^((~b2)& b3 ); + a42 = b2 ^((~b3)& b4 ); + a43 = b3 ^((~b4)& b0 ); + a44 = b4 ^((~b0)& b1 ); + } +} + +/* +** Initialize a new hash. iSize determines the size of the hash +** in bits and should be one of 224, 256, 384, or 512. Or iSize +** can be zero to use the default hash size of 256 bits. +*/ +static void SHA3Init(SHA3Context *p, int iSize){ + memset(p, 0, sizeof(*p)); + p->iSize = iSize; + if( iSize>=128 && iSize<=512 ){ + p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; + }else{ + p->nRate = (1600 - 2*256)/8; + } +#if SHA3_BYTEORDER==1234 + /* Known to be little-endian at compile-time. No-op */ +#elif SHA3_BYTEORDER==4321 + p->ixMask = 7; /* Big-endian */ +#else + { + static unsigned int one = 1; + if( 1==*(unsigned char*)&one ){ + /* Little endian. No byte swapping. */ + p->ixMask = 0; + }else{ + /* Big endian. Byte swap. */ + p->ixMask = 7; + } + } +#endif +} + +/* +** Make consecutive calls to the SHA3Update function to add new content +** to the hash +*/ +static void SHA3Update( + SHA3Context *p, + const unsigned char *aData, + unsigned int nData +){ + unsigned int i = 0; + if( aData==0 ) return; +#if SHA3_BYTEORDER==1234 + if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){ + for(; i+7u.s[p->nLoaded/8] ^= *(u64*)&aData[i]; + p->nLoaded += 8; + if( p->nLoaded>=p->nRate ){ + KeccakF1600Step(p); + p->nLoaded = 0; + } + } + } +#endif + for(; iu.x[p->nLoaded] ^= aData[i]; +#elif SHA3_BYTEORDER==4321 + p->u.x[p->nLoaded^0x07] ^= aData[i]; +#else + p->u.x[p->nLoaded^p->ixMask] ^= aData[i]; +#endif + p->nLoaded++; + if( p->nLoaded==p->nRate ){ + KeccakF1600Step(p); + p->nLoaded = 0; + } + } +} + +/* +** After all content has been added, invoke SHA3Final() to compute +** the final hash. The function returns a pointer to the binary +** hash value. +*/ +static unsigned char *SHA3Final(SHA3Context *p){ + unsigned int i; + if( p->nLoaded==p->nRate-1 ){ + const unsigned char c1 = 0x86; + SHA3Update(p, &c1, 1); + }else{ + const unsigned char c2 = 0x06; + const unsigned char c3 = 0x80; + SHA3Update(p, &c2, 1); + p->nLoaded = p->nRate - 1; + SHA3Update(p, &c3, 1); + } + for(i=0; inRate; i++){ + p->u.x[i+p->nRate] = p->u.x[i^p->ixMask]; + } + return &p->u.x[p->nRate]; +} + +#endif diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index 816c9d38c..30d9da51d 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -26,6 +26,7 @@ add_library(mch OBJECT m_europc.c m_elt.c m_xt_olivetti.c + m_xt_ibm5550.c m_tandy.c m_v86p.c m_at_t3100e.c diff --git a/src/machine/m_at_386sx.c b/src/machine/m_at_386sx.c index 9ad29e2e8..6b5c4414c 100644 --- a/src/machine/m_at_386sx.c +++ b/src/machine/m_at_386sx.c @@ -42,6 +42,7 @@ #include <86box/vid_cga.h> #include <86box/flash.h> #include <86box/machine.h> +#include <86box/sound.h> /* ISA */ /* @@ -369,6 +370,32 @@ machine_at_ama932j_init(const machine_t *model) return ret; } +int +machine_at_tandy1000rsx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/tandy1000rsx/tandy-1000rsx-1-10.00.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_ide_init(model); + + device_add(&headland_ht18c_device); + device_add_params(machine_get_kbc_device(machine), (void *) model->kbc_params); + device_add(&pssj_1e0_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + + return ret; +} + /* Intel 82335 */ int machine_at_adi386sx_init(const machine_t *model) diff --git a/src/machine/m_xt_ibm5550.c b/src/machine/m_xt_ibm5550.c new file mode 100644 index 000000000..e1c842ecb --- /dev/null +++ b/src/machine/m_xt_ibm5550.c @@ -0,0 +1,2132 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the IBM 5550 machine. + * + * The IBM 5550 was launched with three models: + * 5551-Axx: 12" monochrome CRT with 16x16 font + * (replaced by model D) + * 5551-Bxx: 15" monochrome CRT with 24x24 font + * (replaced by model G, J, M) + * 5551-Cxx: 14" color CRT with 16x16 font + * (replaced by model E, H, K, P) + * These first-gen models have 1-3 DSQD diskette drives. + * You need select "Type: 5.25" 720k" in the Settings dialog - Floppy & CD-ROM drives. + * + * Currently, this module only support the model B configuration without hard disk. + * + * Authors: Akamaki. + * + * Copyright 2026 Akamaki. + */ + +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/dma.h> +#include <86box/pic.h> +#include <86box/ppi.h> +#include <86box/nmi.h> +#include <86box/mem.h> +#include <86box/device.h> +#include <86box/lpt.h> +#include <86box/nvr.h> +#include <86box/keyboard.h> +#include <86box/rom.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/fdc_ext.h> +#include <86box/serial.h> +#include <86box/snd_speaker.h> +#include <86box/video.h> +#include <86box/machine.h> +#include <86box/plat_unused.h> +#define EMU_DEVICE_H +#include <86box/pit.h> + +// #define EPOCH_FONTROM_SIZE (1024 * 1024) +// #define EPOCH_FONTROM_MASK 0xffff +// #define EPOCH_FONTROM_BASESBCS 0x98000 +#define EPOCH_VRAM_SBCS 0x38000 +#define EPOCH_VRAM_SBEX 0x30000 +#define EPOCH_INVALIDACCESS8 0xffu +#define EPOCH_INVALIDACCESS16 0xffffu +#define EPOCH_INVALIDACCESS32 0xffffffffu +#define EPOCH_SIZE_VRAM (256 * 1024) /* 0x40000 */ +#define EPOCH_SIZE_CRAM (4 * 1024) /* 0x1000 */ +#define EPOCH_MASK_A000 0x1ffff /* 0x1FFFF */ +#define EPOCH_MASK_CRAM 0xfff /* 0xFFF */ +#define EPOCH_MASK_VRAM 0x3ffff /* 0xFFFFF */ +// #define EPOCH_MASK_VRAMPLANE 0x1ffff /* 0x1FFFF */ +#define EPOCH_PIXELCLOCK 40000000.0 /* 40 MHz interlaced */ + +#define LC_INDEX 0x3D0 +#define LC_DATA 0x3D1 +#define LS_ENABLE 0x3D2 +#define LS_DISABLE 0x3D3 +#define LC_HORIZONTAL_TOTAL 0x00 /* -1 */ +#define LC_HORIZONTAL_DISPLAYED 0x01 +#define LC_H_SYNC_POSITION 0x02 +#define LC_SYNC_WIDTH 0x03 +#define LC_VERTICAL_TOTAL 0x04 /* -1 */ +#define LC_V_TOTAL_ADJUST 0x05 +#define LC_VERTICAL_DISPLAYED 0x06 +#define LC_V_SYNC_POSITION 0x07 +#define LC_INTERLACE_AND_SKEW 0x08 +#define LC_MAXIMUM_SCAN_LINE 0x09 /* -1 */ +#define LC_CURSOR_ROW_START 0x0A +#define LC_CURSOR_ROW_END 0x0B +#define LC_START_ADDRESS_HIGH 0x0C +#define LC_START_ADDRESS_LOW 0x0D +#define LC_CURSOR_LOC_HIGH 0x0E +#define LC_CURSOR_LOC_LOWJ 0x0F +#define LC_LIGHT_PEN_HIGH 0x10 +#define LC_LIGHT_PEN_LOW 0x11 +// #define LV_PORT 0x3E8 +// #define LV_PALETTE_0 0x00 +// #define LV_MODE_CONTROL 0x10 +// #define LV_OVERSCAN_COLOR 0x11 +// #define LV_COLOR_PLANE_ENAB 0x12 +// #define LV_PANNING 0x13 +// #define LV_VIEWPORT1_BG 0x14 +// #define LV_VIEWPORT2_BG 0x15 +// #define LV_VIEWPORT3_BG 0x16 +// #define LV_BLINK_COLOR 0x17 +// #define LV_BLINK_CODE 0x18 +// #define LV_GR_CURSOR_ROTATION 0x19 +// #define LV_GR_CURSOR_COLOR 0x1A +// #define LV_GR_CURSOR_CONTROL 0x1B +// #define LV_COMMAND 0x1C +// #define LV_VP_BORDER_LINE 0x1D +// #define LV_SYNC_POLARITY 0x1F +// #define LV_CURSOR_CODE_0 0x20 +// #define LV_GRID_COLOR_0 0x34 +// #define LV_GRID_COLOR_1 0x35 +// #define LV_GRID_COLOR_2 0x36 +// #define LV_GRID_COLOR_3 0x37 +// #define LV_ATTRIBUTE_CNTL 0x38 +// #define LV_CURSOR_COLOR 0x3A +// #define LV_CURSOR_CONTROL 0x3B +// #define LV_RAS_STATUS_VIDEO 0x3C +// #define LV_PAS_STATUS_CNTRL 0x3D +// #define LV_IDENTIFICATION 0x3E +// #define LV_OUTPUT 0x3E +// #define LV_COMPATIBILITY 0x3F + +#define TIMER_CTR_0 0 //DMA +#define TIMER_CTR_1 1 //8253 timer +#define TIMER_CTR_2 2 //Speaker + +#define EPOCH_IRQ3_BIT (1 << 3) //Keyboard +#define EPOCH_IRQ6_BIT (1 << 6) //Timer + +enum epoch_nvr_ADDR { + epoch_nvr_SECOND1, + epoch_nvr_SECOND10, + epoch_nvr_MINUTE1, + epoch_nvr_MINUTE10, + epoch_nvr_HOUR1, + epoch_nvr_HOUR10, + epoch_nvr_WEEKDAY, + epoch_nvr_DAY1, + epoch_nvr_DAY10, + epoch_nvr_MONTH1, + epoch_nvr_MONTH10, + epoch_nvr_YEAR1, + epoch_nvr_YEAR10, + epoch_nvr_UNKOWN_D, + epoch_nvr_UNKOWN_E, + epoch_nvr_UNKOWN_F, + epoch_nvr_CONTROL /* Internal data for configuration port (I/O 360h) */ +}; + +#ifndef RELEASE_BUILD +// #define ENABLE_EPOCH_LOG 1 +#endif + +#ifdef ENABLE_EPOCH_LOG +// # define ENABLE_EPOCH_DEBUGIO 1 +int epoch_do_log = ENABLE_EPOCH_LOG; + +static void +epoch_log(const char *fmt, ...) +{ + va_list ap; + + if (epoch_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define epoch_log(fmt, ...) +#endif +#ifdef ENABLE_EPOCH_DEBUGIO +# define epoch_iolog epoch_log +#else +# define epoch_iolog(fmt, ...) +#endif + +typedef struct epoch_t { + mem_mapping_t cmapping; + + uint16_t crtc[32]; + // uint16_t crtc_vpreg[128]; + // uint8_t crtc_vpsel; + uint8_t crtmode; + // uint8_t attrc[0x40]; + // int attraddr, attrff; + // int attr_palette_enable; + int outflipflop; + int inflipflop; + int iolatch; + + int crtcaddr; + + uint8_t cgastat; + + // int writemode, readplane; + // uint8_t planemask; + + uint8_t egapal[16]; + uint32_t pallook[64]; + PALETTE vgapal; + + int vtotal, dispend, vsyncstart, vblankstart; + int hdisp, htotal, hdisp_time, rowoffset; + int lowres; + int rowcount; + double clock; + uint32_t memaddr_latch, ca_adj; + + uint64_t dispontime, dispofftime; + pc_timer_t timer; + uint64_t epochconst; + + int dispon; + int hdisp_on; + + uint32_t memaddr, memaddr_backup, cursoraddr; + int vc; + int scanline; + int linepos, vslines, linecountff; + int cursorvisible, cursoron, blink; + int scrollcache; + int char_width; + + int firstline, lastline; + int firstline_draw, lastline_draw; + int displine; + int oddeven; + + /* Attribute Buffer E0000-E0FFFh (4 KB) */ + uint8_t *cram; + /* SBCS Font Buffer D8000-DBFFFh (16 KB) */ + /* APA Buffer A0000-DFFFFh (256 KB) */ + uint8_t *vram; + mem_mapping_t cmap, vmap, paritymap; + /* Font ROM card option (?KB) */ + // struct { + // int bank; + // mem_mapping_t map; + // uint8_t *rom; + // int charset; + // int portdata; + // } fontcard; + // uint8_t *changedvram; + uint32_t vram_display_mask; + + int parityerror; + int parityenabled; + uint8_t parityerroraddr; + int lowmemorydisabled; + int crtioenabled; + + int fullchange; + + void (*render)(struct epoch_t *epoch); + + nvr_t nvr; + int nvrctrl; + int nvrdata; + +} epoch_t; + +static void epoch_recalctimings(epoch_t *epoch); +static void epoch_reset(void *priv); + +/* +[IRQ] +The IBM 5550 has different IRQ assignments like the 6580 Displaywriter System. + +| IRQ | 5550 | Displaywriter | PC/XT | +| --- | ---------- | ---------------------------------- | ---------------- | +| 0 | ? | Incoming data for printer sharing | Timer | +| 1 | Async Comm | Transfer data to commo data link | Keyboard | +| 2 | Fixed Disk | Printer and Mag Card data transfer | Reserved | +| 3 | Keyboard | Keyboard incoming data | Async Comm (Sec) | +| 4 | Diskette | Diskette interrupt | Async Comm (Pri) | +| 5 | ? | Not used | Fixed Disk | +| 6 | Timer | Software timer | Diskette | +| 7 | ? | Error on commo data link | Printer | + +[Memory map] +| Start Address | Function | +| ------------- | ----------------------------------------------------- | +| 0 | 256 KB RAM on System Board | +| 40000h | 128 KB Expansion RAM Card | +| 60000h | 128 KB Expansion RAM Card | +| 80000h | 128 KB Expansion RAM Card | +| A0000h | 256 KB Video RAM | +| E0000h | 4 KB Code/Attribute Buffer | +| E8000h | ? KB Hard Disk Control Local Memory (not implemented) | +| F0000h | Kanji Font Card (not implemented) | +| FC000h | ROM | +*/ + +static void +epoch_out(uint16_t addr, uint16_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + epoch_iolog("%04X:%04X epoch Out addr %03X val %02X\n", cs >> 4, cpu_state.pc, addr, val); + switch (addr) { + case LC_INDEX: + epoch->crtcaddr = val; + break; + case LC_DATA: + if (epoch->crtcaddr > 0x1f) + return; + if (epoch->crtioenabled == 0) + return; + if (!(epoch->crtcaddr == LC_CURSOR_LOC_HIGH || epoch->crtcaddr == LC_CURSOR_LOC_LOWJ)) + epoch_iolog("%04X:%04X epoch Out addr %03X idx %02X val %02X (%d)\n", cs >> 4, cpu_state.pc, addr, epoch->crtcaddr, val, val); + if (!(epoch->crtc[epoch->crtcaddr] ^ val)) + return; + // switch (epoch->crtcaddr) { + // // case LC_CRTC_OVERFLOW: + // // // return; + // // break; + // case LC_MAXIMUM_SCAN_LINE: + // // if (!(epoch->ioctl[LS_MODE] & 0x01)) /* 16 or 256 color graphics mode */ + // // val = 0; + // break; + // // case LC_VERTICAL_TOTALJ: /* Vertical Total */ + // // break; + // } + switch (epoch->crtcaddr) { + case LC_START_ADDRESS_HIGH: + case LC_CURSOR_LOC_HIGH: + case LC_LIGHT_PEN_HIGH: + val &= 0x3F; + break; + } + epoch->crtc[epoch->crtcaddr] = val; + switch (epoch->crtcaddr) { + case LC_HORIZONTAL_DISPLAYED: + case LC_VERTICAL_DISPLAYED: + case LC_MAXIMUM_SCAN_LINE: + case LC_START_ADDRESS_HIGH: + case LC_START_ADDRESS_LOW: + epoch->fullchange = changeframecount; + epoch_recalctimings(epoch); + break; + default: + break; + } + break; + case LS_ENABLE: + // mem_mapping_disable(&epoch->paritymap); + epoch->crtioenabled = 1; + mem_mapping_enable(&epoch->cmap); + mem_mapping_enable(&epoch->vmap); + break; + case LS_DISABLE: + epoch->crtioenabled = 0; + mem_mapping_disable(&epoch->cmap); + mem_mapping_disable(&epoch->vmap); + // mem_mapping_enable(&epoch->paritymap); + break; + case 0x3D8: + epoch->crtmode = val; + epoch_recalctimings(epoch); + // epoch->attrff ^= 1; + break; + // case LV_PORT: + // // epoch_iolog("epoch Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, epoch->attrff,cs >> 4, cpu_state.pc); + // if (!epoch->attrff) { + // epoch->attraddr = val & 0x3f; + // if ((val & 0x20) != (epoch->attr_palette_enable & 0x20)) { + // epoch->fullchange = 3; + // epoch->attr_palette_enable = val & 0x20; + // epoch_recalctimings(epoch); + // } + // // epoch_iolog("set attraddr: %X\n", epoch->attraddr); + // } else { + // if ((epoch->attraddr == LV_PANNING) && (epoch->attrc[LV_PANNING] != val)) + // epoch->fullchange = changeframecount; + // if (epoch->attrc[epoch->attraddr & 0x3f] != val) + // epoch_iolog("attr changed %x: %x -> %x\n", epoch->attraddr & 0x3f, epoch->attrc[epoch->attraddr & 0x3f], val); + // epoch->attrc[epoch->attraddr & 0x3f] = val; + // // epoch_iolog("set attrc %x: %x\n", epoch->attraddr & 31, val); + // if (epoch->attraddr < 16) + // epoch->fullchange = changeframecount; + // if (epoch->attraddr == LV_MODE_CONTROL || epoch->attraddr < 0x10) { + // for (uint8_t c = 0; c < 16; c++) { + // // if (epoch->attrc[LV_MODE_CONTROL] & 0x80) + // // epoch->egapal[c] = epoch->attrc[c] & 0xf; + // // else + // // epoch->egapal[c] = epoch->attrc[c] & 0x3f; + // } + // } + // switch (epoch->attraddr) { + // case LV_COLOR_PLANE_ENAB: + // if ((val & 0xff) != epoch->plane_mask) + // epoch->fullchange = changeframecount; + // epoch->plane_mask = val & 0xff; + // break; + // case LV_CURSOR_CONTROL: + // switch (val & 0x18) { + // case 0x08: /* fast blink */ + // epoch->blinkconf = 0x10; + // break; + // case 0x18: /* slow blink */ + // epoch->blinkconf = 0x20; + // break; + // default: /* no blink */ + // epoch->blinkconf = 0xff; + // break; + // } + // break; + // case LV_MODE_CONTROL: + // case LV_ATTRIBUTE_CNTL: + // case LV_COMPATIBILITY: + // epoch_recalctimings(epoch); + // break; + // default: + // break; + // } + // } + // epoch->attrff ^= 1; + // break; + // case LV_PORT+1: + // /* VZ Editor's CURSOR.COM writes data via this port */ + // epoch->attrc[epoch->attraddr & 0x3f] = val; + // break; + default: + epoch_iolog("epoch? Out addr %03X val %02X\n", addr, val); + break; + } +} + +static uint16_t +epoch_in(uint16_t addr, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + uint16_t temp = 0xff; + + switch (addr) { + case LC_INDEX: + temp = epoch->crtcaddr; + break; + case LC_DATA: + if (epoch->crtcaddr > 0x1f) + return EPOCH_INVALIDACCESS16; + if (epoch->crtioenabled == 0) + return EPOCH_INVALIDACCESS16; + temp = epoch->crtc[epoch->crtcaddr]; + break; + // case LV_PORT: + // temp = epoch->attraddr | epoch->attr_palette_enable; + // break; + // case LV_PORT + 1: + // switch (epoch->attraddr) { + // case LV_RAS_STATUS_VIDEO: /* this maybe equivalent to 3ba / 3da ISR1 */ + // if (epoch->cgastat & 0x01) + // epoch->cgastat &= ~0x30; + // else + // epoch->cgastat ^= 0x30; /* toggle */ + // if (epoch->cgastat & 0x08) + // epoch->cgastat &= ~0x08; + // else + // epoch->cgastat ^= 0x08; /* toggle */ + // temp = epoch->cgastat; + // break; + // case LV_IDENTIFICATION: + // temp = 0x28; + // break; + // default: + // temp = epoch->attrc[epoch->attraddr]; + // break; + // } + // // epoch_iolog("epoch In %04X(%02X) %04X %04X:%04X\n", addr, epoch->attraddr, temp, cs >> 4, cpu_state.pc); + // epoch->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */ + // break; + case 0x3DA: + temp = 0xff; + if (!(epoch->crtmode & 0x08)) {/* The video out is active */ + if(epoch->cgastat & 8) + temp &= 0x7f; + } + temp &= 0xfe;/* equipment ? color or monochrome monitor */ + // temp |= 0x01; + break; + } + if (addr != 0x3DA) + epoch_iolog("%04X:%04X epoch In %04X %04X\n", cs >> 4, cpu_state.pc, addr, temp); + return temp; +} +/* + * Write I/O + * out b(idx), out b(data), out b(data) + * out b(idx), out w(data) + * out b(idx), out w(data), out b(data) + * out w(idx) + * Read I/O + * out b(idx), in b(data) + * out b(idx), in b, in b(data) + * out b(idx), in w(data) + */ +static void +epoch_outb(uint16_t addr, uint8_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + // epoch_iolog("%04X:%04X epoch Outb addr %03X val %02X es:di=%x:%x ds:si=%x:%x\n", cs >> 4, cpu_state.pc, addr, val, ES, DI, DS, SI); + epoch->inflipflop = 0; + switch (addr) { + // case LS_DATA: + // case LF_DATA: + case LC_DATA: + if (epoch->outflipflop) { + /* out b(idx), out b(data), out b(data) */ + epoch->iolatch |= (uint16_t) val << 8; + epoch->outflipflop = 0; + } else { // + epoch->iolatch = val; + epoch->outflipflop = 1; + } + break; + // case LS_INDEX: + // case LF_INDEX: + case LC_INDEX: + default: + epoch->iolatch = val; + epoch->outflipflop = 0; + break; + } + epoch_out(addr, epoch->iolatch, epoch); +} +static void +epoch_outw(uint16_t addr, uint16_t val, void *priv) +{ + epoch_iolog("epoch Outw addr %03X val %04X\n", addr, val); + epoch_t *epoch = (epoch_t *) priv; + epoch->inflipflop = 0; + switch (addr) { + // case LS_INDEX: + // case LF_INDEX: + case LC_INDEX: + // case LG_INDEX: + epoch_out(addr, val & 0xff, epoch); + epoch->iolatch = val >> 8; + epoch_out(addr + 1, epoch->iolatch, epoch); + epoch->outflipflop = 1; + break; + // case LV_PORT: + // // epoch->attrff = 0; + // epoch_out(addr, val & 0xff, epoch); + // epoch_out(addr, val >> 8, epoch); + // epoch->outflipflop = 0; + // break; + // case LS_DATA: + // case LF_DATA: + case LC_DATA: + // case LG_DATA: + default: + epoch_out(addr, val, epoch); + epoch->outflipflop = 0; + break; + } +} +static uint8_t +epoch_inb(uint16_t addr, void *priv) +{ + uint8_t temp; + epoch_t *epoch = (epoch_t *) priv; + epoch->outflipflop = 0; + switch (addr) { + case LC_DATA: + if (epoch->inflipflop) { + /* out b(idx), in b(low data), in b(high data) */ + temp = epoch->iolatch >> 8; + epoch->inflipflop = 0; + } else { // + epoch->iolatch = epoch_in(addr, epoch); + temp = epoch->iolatch & 0xff; + epoch->inflipflop = 1; + } + break; + // case LS_INDEX: + // case LF_INDEX: + case LC_INDEX: + // case LS_DATA: + // case LF_DATA: + default: + temp = epoch_in(addr, epoch) & 0xff; + epoch->inflipflop = 0; + break; + } + // epoch_iolog("epoch Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + return temp; +} +static uint16_t +epoch_inw(uint16_t addr, void *priv) +{ + uint16_t temp; + epoch_t *epoch = (epoch_t *) priv; + epoch->inflipflop = 0; + epoch->outflipflop = 0; + temp = epoch_in(addr, epoch); + epoch_iolog("epoch Inw addr %03X val %04X\n", addr, temp); + return temp; +} + +/* Get character line pattern from jfont rom or gaiji volatile memory */ +static uint32_t +getfont_ps55dbcs(int32_t code, int32_t line, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + uint32_t font = 0; + if (code < 1536) { + code *= 0x80; + font = epoch->vram[code + line * 4]; + font <<= 8; + font |= epoch->vram[code + line * 4 + 1]; + font <<= 8; + font |= epoch->vram[code + line * 4 + 2]; + font <<= 8; + font |= epoch->vram[code + line * 4 + 3]; + } else + font = EPOCH_INVALIDACCESS32; + return font; +} + +/* Get the foreground color from the attribute byte */ +static uint8_t +getPS55ForeColor(uint8_t attr, epoch_t *epoch) +{ + uint8_t foreground = ~attr & 0x08; /* 0000 1000 */ + foreground <<= 2; /* 0010 0000 */ + foreground |= ~attr & 0xc0; /* 1110 0000 */ + foreground >>= 4; /* 0000 1110 */ + // if (epoch->attrc[LV_PAS_STATUS_CNTRL] & 0x40) + // foreground |= 0x01; /* bright color palette */ + return foreground; +} + +static void +epoch_render_blank(epoch_t *epoch) +{ + int x, xx; + + if (epoch->firstline_draw == 2000) + epoch->firstline_draw = epoch->displine; + epoch->lastline_draw = epoch->displine; + + for (x = 0; x < epoch->hdisp + epoch->scrollcache; x++) { + for (xx = 0; xx < epoch->char_width; xx++) + ((uint32_t *) buffer32->line[epoch->displine])[(x * epoch->char_width) + xx] = 0; + } +} +/* Display Adapter Mode 8, E Drawing */ +static void +epoch_render_text(epoch_t *epoch) +{ + if (epoch->firstline_draw == 2000) + epoch->firstline_draw = epoch->displine; + epoch->lastline_draw = epoch->displine; + + if (epoch->fullchange) { + int offset = (8 - epoch->scrollcache) + 24; + uint32_t *p = &((uint32_t *) buffer32->line[epoch->displine])[offset]; + int x; + int drawcursor; + uint8_t chr, attr; + int fg, bg; + uint32_t chr_dbcs; + int chr_wide = 0; + // int colormode = ((epoch->attrc[LV_PAS_STATUS_CNTRL] & 0x80) == 0x80); + int colormode = 0; + // epoch_log("displ: %x, first: %x, epochma: %x, epochsc: %x\n", + // epoch->displine , epoch->firstline_draw, epoch->memaddr, epoch->scanline); + for (x = 0; x < epoch->hdisp; x += 13) { + chr = epoch->cram[(epoch->memaddr) & EPOCH_MASK_CRAM]; + attr = epoch->cram[(epoch->memaddr + 1) & EPOCH_MASK_CRAM]; + // if(chr!=0x20) epoch_log("chr: %x, attr: %x ", chr, attr); + if (colormode) /* IO 3E8h, Index 1Dh */ + { /* --Parse attribute byte in color mode-- */ + bg = 0; /* bg color is always black (the only way to change background color is programming PAL) */ + fg = getPS55ForeColor(attr, epoch); + if (attr & 0x04) { /* reverse 0000 0100 */ + bg = fg; + fg = 0; + } + } else { /* --Parse attribute byte in monochrome mode-- */ + if (attr & 0x08) + fg = 3; /* Highlight 0000 1000 */ + else + fg = 2; + bg = 0; /* Background is always color #0 (default is black) */ + if (!(~attr & 0xCC)) /* Invisible 11xx 11xx -> 00xx 00xx */ + { + fg = bg; + attr &= 0x33; /* disable blinkking, underscore, highlight and reverse */ + } + if (attr & 0x04) { /* reverse 0000 0100 */ + bg = fg; + fg = 0; + } + /* Blinking 1000 0000 */ + fg = ((epoch->blink & 0x20) || (!(attr & 0x80))) ? fg : bg; + // if(chr!=0x20) epoch_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, epoch->egapal[fg], epoch->pallook[epoch->egapal[fg]]); + } + /* Draw character */ + for (uint32_t n = 0; n < 13; n++) + p[n] = epoch->pallook[epoch->egapal[bg]]; /* draw blank */ + /* SBCS or DBCS left half */ + if (chr_wide == 0) { + if (attr & 0x01) + chr_wide = 1; + // chr_wide = 0; + /* Stay drawing If the char code is DBCS and not at last column. */ + if (chr_wide) { + /* Get high DBCS code from the next video address */ + chr_dbcs = epoch->cram[(epoch->memaddr + 2) & EPOCH_MASK_CRAM]; + chr_dbcs <<= 8; + chr_dbcs |= chr; + /* Get the font pattern */ + uint32_t font = getfont_ps55dbcs(chr_dbcs, epoch->scanline, epoch); + /* Draw 13 dots */ + for (uint32_t n = 0; n < 13; n++) { + p[n] = epoch->pallook[epoch->egapal[(font & 0x80000000) ? fg : bg]]; + font <<= 1; + } + } else { + /* the char code is SBCS (ANK) */ + uint32_t fontbase; + if (attr & 0x02) /* second map of SBCS font */ + fontbase = EPOCH_VRAM_SBEX; + else + fontbase = EPOCH_VRAM_SBCS; + uint16_t font = epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4]; /* w13xh29 font */ + font <<= 8; + font |= epoch->vram[fontbase + chr * 0x80 + epoch->scanline * 4 + 1]; /* w13xh29 font */ + // if(chr!=0x20) epoch_log("memaddr: %x, scanline: %x, chr: %x, font: %x ", epoch->memaddr, epoch->scanline, chr, font); + /* Draw 13 dots */ + for (uint32_t n = 0; n < 13; n++) { + p[n] = epoch->pallook[epoch->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + } + } + /* right half of DBCS */ + else { + uint32_t font = getfont_ps55dbcs(chr_dbcs, epoch->scanline, epoch); + /* Draw 13 dots */ + for (uint32_t n = 0; n < 13; n++) { + p[n] = epoch->pallook[epoch->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + chr_wide = 0; + } + /* Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. */ + if (epoch->scanline == 28 && attr & 0x40 && !colormode) { /* Underscore only in monochrome mode */ + for (uint32_t n = 0; n < 13; n++) + p[n] = epoch->pallook[epoch->egapal[fg]]; /* under line (white) */ + } + /* Column 1 (Vertical Line) */ + if (attr & 0x10) { + p[0] = epoch->pallook[epoch->egapal[2]]; /* vertical line (white) */ + } + if (epoch->scanline == 0 && attr & 0x20) { /* HGrid */ + for (uint32_t n = 0; n < 13; n++) + p[n] = epoch->pallook[epoch->egapal[2]]; /* horizontal line (white) */ + } + /* Drawing text cursor */ + drawcursor = ((epoch->memaddr == epoch->cursoraddr) && epoch->cursorvisible && epoch->cursoron); + if (drawcursor && epoch->scanline >= epoch->crtc[LC_CURSOR_ROW_START] && epoch->scanline <= epoch->crtc[LC_CURSOR_ROW_END]) { + // int cursorwidth = (epoch->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); + int cursorwidth = 13; + int cursorcolor = 2; /* Choose color 2 if mode 8 */ + fg = ((attr & 0x08) ? 3 : 2); + bg = 0; + if (attr & 0x04) { /* Color 0 if reverse */ + bg = fg; + fg = 0; + } + for (uint32_t n = 0; n < cursorwidth; n++) + if (p[n] == epoch->pallook[epoch->egapal[cursorcolor]] || epoch->egapal[bg] == epoch->egapal[cursorcolor]) + p[n] = (p[n] == epoch->pallook[epoch->egapal[bg]]) ? epoch->pallook[epoch->egapal[fg]] : epoch->pallook[epoch->egapal[bg]]; + else + p[n] = (p[n] == epoch->pallook[epoch->egapal[bg]]) ? epoch->pallook[epoch->egapal[cursorcolor]] : p[n]; + } + epoch->memaddr += 2; + p += 13; + } + } +} + +static void +epoch_render_color_4bpp(epoch_t *epoch) +{ + // int changed_offset = epoch->memaddr >> 9; + // epoch_log("memaddr %x cf %x\n", epoch->memaddr, changed_offset); + // epoch->plane_mask &= 1; /*safety */ + + // if (epoch->changedvram[changed_offset] || epoch->changedvram[changed_offset + 1] || epoch->fullchange) { + int x; + int offset = (8 - epoch->scrollcache) + 24; + uint32_t *p = &((uint32_t *) buffer32->line[epoch->displine])[offset]; + + if (epoch->firstline_draw == 2000) + epoch->firstline_draw = epoch->displine; + epoch->lastline_draw = epoch->displine; + // epoch_log("d %X\n", epoch->memaddr); + int readvaddr = (epoch->memaddr * 8) + (epoch->scanline * 128); + for (x = 0; x <= epoch->hdisp; x += 8) /* hdisp = 1024 */ + { + uint8_t edat[8]; + uint8_t dat; + + /* get 8 pixels from vram */ + readvaddr &= epoch->vram_display_mask; + *(uint8_t *) (&edat[0]) = *(uint8_t *) (&epoch->vram[readvaddr]); + readvaddr += 1; + + dat = ((edat[0] >> 7) & 1); + p[0] = epoch->pallook[epoch->egapal[dat]]; + dat = ((edat[0] >> 6) & 1); + p[1] = epoch->pallook[epoch->egapal[dat]]; + dat = ((edat[0] >> 5) & 1); + p[2] = epoch->pallook[epoch->egapal[dat]]; + dat = ((edat[0] >> 4) & 1); + p[3] = epoch->pallook[epoch->egapal[dat]]; + dat = ((edat[0] >> 3) & 1); + p[4] = epoch->pallook[epoch->egapal[dat]]; + dat = ((edat[0] >> 2) & 1); + p[5] = epoch->pallook[epoch->egapal[dat]]; + dat = ((edat[0] >> 1) & 1); + p[6] = epoch->pallook[epoch->egapal[dat]]; + dat = ((edat[0] >> 0) & 1); + p[7] = epoch->pallook[epoch->egapal[dat]]; + p += 8; + } +} + +/* + INT 10h video modes supported in DOS K3.44. + Mode Type Colors Text Base Address PELs Render + 2 A/N 3 80 x 25 E0000h 1040 x 725 text + 8 A/N/K 3 80 x 25 E0000h 1040 x 725 text + Ah APA 2 78 x 25 A0000h 1024 x 768 color_4bpp + Bh APA 16 40 x 25 A0000h 360 x 512 n/a + Ch APA 16 80 x 25 A0000h 720 x 512 n/a + Dh APA 16 78 x 25 A0000h 1024 x 768 n/a + Eh A/N/K 16 80 x 25 E0000h 1040 x 725 n/a +*/ +static void +epoch_recalctimings(epoch_t *epoch) +{ + double crtcconst; + double _dispontime, _dispofftime, disptime; + + epoch->vblankstart = epoch->crtc[LC_VERTICAL_TOTAL] & 0x7f; + epoch->dispend = epoch->crtc[LC_VERTICAL_DISPLAYED] & 0x7f; + epoch->vsyncstart = epoch->crtc[LC_V_SYNC_POSITION] & 0x7f; + epoch->vblankstart += 1; + epoch->vtotal = epoch->vblankstart + (epoch->crtc[LC_V_TOTAL_ADJUST] & 0x1f); + epoch->hdisp = epoch->crtc[LC_HORIZONTAL_DISPLAYED] & 0xff; + + // epoch->hdisp -= epoch->crtc[LC_START_H_DISPLAY_ENAB]; + // epoch->dispend -= epoch->crtc[LC_START_V_DISPLAY_ENAB]; + //epoch_log("Dispend %d\n", epoch->dispend); + // epoch->vsyncstart += 1; + //epoch->vtotal += 1; + + epoch->htotal = epoch->crtc[LC_HORIZONTAL_TOTAL] & 0xff; + epoch->htotal += 1; + + // epoch->rowoffset = epoch->crtc[LC_OFFSET]; /* number of bytes in a scanline */ + epoch->rowoffset = epoch->crtc[LC_HORIZONTAL_DISPLAYED] & 0xff; + + epoch->clock = epoch->epochconst; + + if (epoch->vtotal == 0) + epoch->vtotal = epoch->vsyncstart = epoch->vblankstart = 32; + if (epoch->htotal == 0) + epoch->htotal = epoch->dispend = epoch->hdisp = 64; + if (epoch->rowoffset == 0) + epoch->rowoffset = 64 * 2; /* To avoid causing a DBZ error */ + + epoch->memaddr_latch = ((epoch->crtc[LC_START_ADDRESS_HIGH] & 0x3f) << 8) | epoch->crtc[LC_START_ADDRESS_LOW]; + + epoch->ca_adj = 0; + epoch->rowcount = epoch->crtc[LC_MAXIMUM_SCAN_LINE] & 0x1f; + epoch->rowcount += 1; + + epoch->vtotal *= (epoch->rowcount + 1); + epoch->dispend *= (epoch->rowcount + 1); + epoch->vsyncstart *= (epoch->rowcount + 1); + epoch->vblankstart *= (epoch->rowcount + 1); + + epoch->hdisp_time = epoch->hdisp; + + /* determine display mode */ + if (epoch->crtmode & 0x02) { + epoch->hdisp *= 16; + epoch->char_width = 16; + /* PS/55 8-color */ + epoch_log("Set videomode to PS/55 4 bpp graphics.\n"); + epoch->render = epoch_render_color_4bpp; + epoch->vram_display_mask = EPOCH_MASK_A000; + } else { + /* PS/55 text(color/mono) */ + epoch_log("Set videomode to PS/55 Mode 8/E text.\n"); + epoch->render = epoch_render_text; + epoch->vram_display_mask = EPOCH_MASK_CRAM; + epoch->hdisp *= 13; + epoch->char_width = 13; + } + if (epoch->crtmode & 0x08) + epoch->render = epoch_render_blank; + + if (epoch->vblankstart < epoch->vsyncstart) + epoch->vsyncstart = epoch->vblankstart; + if (epoch->vsyncstart < epoch->dispend) + epoch->dispend = epoch->vsyncstart; + + crtcconst = epoch->clock * epoch->char_width; + + disptime = epoch->htotal; + _dispontime = epoch->hdisp_time; + + epoch_log("Disptime %f dispontime %f hdisp %i\n", disptime, _dispontime, epoch->hdisp); + + _dispofftime = disptime - _dispontime; + _dispontime *= crtcconst; + _dispofftime *= crtcconst; + + epoch->dispontime = (uint64_t) _dispontime; + epoch->dispofftime = (uint64_t) _dispofftime; + if (epoch->dispontime < TIMER_USEC) + epoch->dispontime = TIMER_USEC; + if (epoch->dispofftime < TIMER_USEC) + epoch->dispofftime = TIMER_USEC; + epoch_log("epoch horiz display end %i vidclock %f htotal %i\n", epoch->hdisp, epoch->clock, epoch->htotal); + epoch_log("epoch vert display end %i max row %i vsyncstart %i vtotal %i\n",epoch->dispend,epoch->rowcount,epoch->vsyncstart,epoch->vtotal); + epoch_log("epoch dispon %lu dispoff %lu on(us) %f off(us) %f\n",epoch->dispontime, epoch->dispofftime, + (double)epoch->dispontime / (double)cpuclock / (double) (1ULL << 32) * 1000000.0, + (double)epoch->dispofftime / (double)cpuclock / (double) (1ULL << 32) * 1000000.0); +} + +static void +epoch_doblit(int wx, int wy, epoch_t *epoch) +{ + if (wx != xsize || wy != ysize) { + xsize = wx; + ysize = wy; + set_screen_size(xsize, ysize); + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(32, 0, xsize, ysize); + frames++; + + video_res_x = wx; + video_res_y = wy; + video_bpp = 8; +} + +static void +epoch_poll(void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + int x; + + if (!epoch->linepos) { + timer_advance_u64(&epoch->timer, epoch->dispofftime); + + epoch->cgastat |= 1; + epoch->linepos = 1; + + if (epoch->dispon) { + epoch->hdisp_on = 1; + + epoch->memaddr &= epoch->vram_display_mask; + if (epoch->firstline == 2000) { + epoch->firstline = epoch->displine; + video_wait_for_buffer(); + } + + if((epoch->displine ^ !epoch->oddeven) & 1) + epoch->render(epoch); + + if (epoch->lastline < epoch->displine) + epoch->lastline = epoch->displine; + } + + // epoch_log("%03i %06X %06X\n", epoch->displine, epoch->memaddr,epoch->vram_display_mask); + epoch->displine++; + if ((epoch->cgastat & 8) && ((epoch->displine & 0xf) == (epoch->vblankstart & 0xf)) && epoch->vslines) { + // epoch_log("Vsync off at line %i\n",displine); + epoch->cgastat &= ~8; + } + epoch->vslines++; + if (epoch->displine > 2000) + epoch->displine = 0; + } else { + // epoch_log("VC %i memaddr %05X\n", epoch->vc, epoch->memaddr); + timer_advance_u64(&epoch->timer, epoch->dispontime); + + if (epoch->dispon) + epoch->cgastat &= ~1; + epoch->hdisp_on = 0; + + epoch->linepos = 0; + if (epoch->scanline == (epoch->crtc[LC_CURSOR_ROW_END] & 0x1f)) + epoch->cursorvisible = 0; + if (epoch->dispon) { + if (epoch->scanline == epoch->rowcount) { + epoch->linecountff = 0; + epoch->scanline = 0; + + epoch->memaddr_backup += (epoch->rowoffset << 1); /* interlace */ + epoch->memaddr_backup &= epoch->vram_display_mask; + epoch->memaddr = epoch->memaddr_backup; + } else { + epoch->linecountff = 0; + epoch->scanline++; + epoch->scanline &= 0x1f; + epoch->memaddr = epoch->memaddr_backup; + } + } + + epoch->vc++; + epoch->vc &= 0x7ff; + + if (epoch->vc == epoch->dispend) { + epoch->dispon = 0; + if (!(epoch->crtmode & 0x02)) { /* in text mode */ + // if (epoch->attrc[LV_CURSOR_CONTROL] & 0x01) /* cursor blinking */ + // { + // epoch->cursoron = (epoch->blink | 1) & epoch->blinkconf; + epoch->cursoron = 1; + // } else { + // epoch->cursoron = 0; + // } + if (!(epoch->blink & (0x10 - 1))) /* force redrawing for cursor and blink attribute */ + epoch->fullchange = changeframecount; + } + epoch->blink++; + + // for (x = 0; x <= (EPOCH_MASK_VRAMPLANE >> 9); x++) { + // if (epoch->changedvram[x]) + // epoch->changedvram[x]--; + // } + // memset(changedvram,0,2048); del + if (epoch->fullchange) { + epoch->fullchange--; + } + } + if (epoch->vc == epoch->vsyncstart) { + int wx, wy; + // epoch_log("VC vsync %i %i\n", epoch->firstline_draw, epoch->lastline_draw); + epoch->dispon = 0; + epoch->cgastat |= 8; + x = epoch->hdisp; + + if (!epoch->oddeven) + epoch->lastline++; + if (epoch->oddeven) + epoch->firstline--; + + wx = x; + wy = epoch->lastline - epoch->firstline; + + epoch_doblit(wx, wy, epoch); + + epoch->firstline = 2000; + epoch->lastline = 0; + + epoch->firstline_draw = 2000; + epoch->lastline_draw = 0; + + epoch->oddeven ^= 1; + + epoch->vslines = 0; + + epoch->memaddr + = epoch->memaddr_backup = epoch->memaddr_latch << 1; + epoch->cursoraddr = ((epoch->crtc[LC_CURSOR_LOC_HIGH] << 8) | epoch->crtc[LC_CURSOR_LOC_LOWJ]) + epoch->ca_adj; + epoch->cursoraddr <<= 1; + + // epoch_log("Addr %08X vson %03X vsoff %01X\n",epoch->memaddr,epoch->vsyncstart,epoch->crtc[0x11]&0xF); + } + if (epoch->vc == epoch->vtotal) { + // epoch_log("VC vtotal\n"); + // printf("Frame over at line %i %i %i %i\n",displine,vc,epoch_vsyncstart,epoch_dispend); + epoch->vc = 0; + epoch->scanline = 0; + epoch->dispon = 1; + epoch->displine = 0; + // epoch->scrollcache = epoch->attrc[LV_PANNING] & 0x07; + epoch->scrollcache = 0; + } + if (epoch->scanline == (epoch->crtc[LC_CURSOR_ROW_START] & 31)) + epoch->cursorvisible = 1; + } +} + +static void +epoch_vram_write(uint32_t addr, uint8_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + // if ((addr & ~0xfff) != 0xE0000) return; + addr -= 0xA0000; + addr &= EPOCH_MASK_VRAM; + epoch->vram[addr] = val; + epoch->fullchange = changeframecount; + // if(val == 0x66) + // epoch_log("66 %04X:%04X %04X:%04X>%04X:%04X\n", cs >> 4, cpu_state.pc, DS, SI,ES,DI); +} +static void +epoch_vram_writeb(uint32_t addr, uint8_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + // epoch_log("epoch_vram_writeb: Write to %x, val %x\n", addr, val); + cycles -= video_timing_write_b; + epoch_vram_write(addr, val, epoch); +} +static void +epoch_vram_writew(uint32_t addr, uint16_t val, void *priv) +{ + // epoch_log("epoch_vram_writ ew: Write to %x, val %x\n", addr, val); + epoch_t *epoch = (epoch_t *) priv; + cycles -= video_timing_write_w; + epoch_vram_write(addr, val & 0xff, epoch); + epoch_vram_write(addr + 1, val >> 8, epoch); +} + +static uint8_t +epoch_vram_read(uint32_t addr, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + // if ((addr & ~epoch_MASK_CRAM) != 0xE0000) + // return epoch_INVALIDACCESS8; + addr -= 0xA0000; + addr &= EPOCH_MASK_VRAM; + return epoch->vram[addr]; +} +static uint8_t +epoch_vram_readb(uint32_t addr, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + cycles -= video_timing_read_b; + return epoch_vram_read(addr, epoch); +} + +static uint16_t +epoch_vram_readw(uint32_t addr, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + cycles -= video_timing_read_w; + return epoch_vram_read(addr, epoch) | (epoch_vram_read(addr + 1, epoch) << 8); +} + + +static void +epoch_cram_write(uint32_t addr, uint8_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + // if ((addr & ~0xfff) != 0xE0000) return; + addr &= EPOCH_MASK_CRAM; + epoch->cram[addr] = val; + epoch->fullchange = changeframecount;; + // epoch_log("cw %04X:%04X %04X %02X\n", cs >> 4, cpu_state.pc, addr, val); +} +static void +epoch_cram_writeb(uint32_t addr, uint8_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + // epoch_log("epoch_cram_writeb: Write to %x, val %x\n", addr, val); + cycles -= video_timing_write_b; + epoch_cram_write(addr, val, epoch); +} +static void +epoch_cram_writew(uint32_t addr, uint16_t val, void *priv) +{ + // epoch_log("epoch_cram_writ ew: Write to %x, val %x\n", addr, val); + epoch_t *epoch = (epoch_t *) priv; + cycles -= video_timing_write_w; + epoch_cram_write(addr, val & 0xff, epoch); + epoch_cram_write(addr + 1, val >> 8, epoch); +} + +static uint8_t +epoch_cram_read(uint32_t addr, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + // if ((addr & ~epoch_MASK_CRAM) != 0xE0000) + // return epoch_INVALIDACCESS8; + addr &= EPOCH_MASK_CRAM; + return epoch->cram[addr]; +} +static uint8_t +epoch_cram_readb(uint32_t addr, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + cycles -= video_timing_read_b; + return epoch_cram_read(addr, epoch); +} + +static uint16_t +epoch_cram_readw(uint32_t addr, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + cycles -= video_timing_read_w; + return epoch_cram_read(addr, epoch) | (epoch_cram_read(addr + 1, epoch) << 8); +} + +static uint8_t +epoch_parity_readb(uint32_t addr, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + if ((epoch->parityerror != 0) && (epoch->parityenabled != 0)) { + epoch->parityerroraddr = (addr >> 16) & 0xFF; /* X000:0 */ + epoch_log("%04X:%04X perror at %0X\n", cs >> 4, cpu_state.pc, addr); + if (nmi_mask) + nmi_raise(); + } + if (epoch->lowmemorydisabled) { + if ((addr >= 0x40000) && (addr < 0xA0000)) { + epoch_log("%04X:%04X mrerror at %0X\n", cs >> 4, cpu_state.pc, addr); + return EPOCH_INVALIDACCESS8; + } + } + // return EPOCH_INVALIDACCESS8; + return mem_read_ram(addr, priv); +} + +static uint16_t +epoch_parity_readw(uint32_t addr, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + if ((epoch->parityerror != 0) && (epoch->parityenabled != 0)) { + epoch->parityerroraddr = (addr >> 16) & 0xFF; + epoch_log("%04X:%04X perror at %X\n", cs >> 4, cpu_state.pc, addr); + if (nmi_mask) + nmi_raise(); + } + if (epoch->lowmemorydisabled) { + if ((addr >= 0x40000) && (addr < 0xA0000)) { + epoch_log("%04X:%04X mrerror at %X\n", cs >> 4, cpu_state.pc, addr); + return EPOCH_INVALIDACCESS16; + } + } + return mem_read_ramw(addr, priv); +} + +static void +epoch_parity_writeb(uint32_t addr, uint8_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + // epoch_log("%04X:%04X mw %0X\n", cs >> 4, cpu_state.pc, addr); + if (epoch->parityenabled == 0) + epoch->parityerror = 1; + if (epoch->lowmemorydisabled) { + if ((addr >= 0x40000) && (addr < 0xA0000)) { + epoch_log("%04X:%04X mwerror at %X\n", cs >> 4, cpu_state.pc, addr); + if (epoch->parityenabled) + epoch->parityerror = 1; + return; + } + } + // if (val == 0xcb) + // epoch_log("CB %04X:%04X %04X:%04X>%04X:%04X\n", cs >> 4, cpu_state.pc, DS, SI, ES, DI); + mem_write_ram(addr, val, priv); +} +static void +epoch_parity_writew(uint32_t addr, uint16_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + if (epoch->parityenabled == 0) + epoch->parityerror = 1; + if (epoch->lowmemorydisabled) { + if ((addr >= 0x40000) && (addr < 0xA0000)) { + epoch_log("%04X:%04X mwerror at %X\n", cs >> 4, cpu_state.pc, addr); + if (epoch->parityenabled) + epoch->parityerror = 1; + return; + } + } + mem_write_ramw(addr, val, priv); +} + +static uint8_t +epoch_misc_in(uint16_t port, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + uint8_t ret = 0xff; + + switch (port) { +/* +I/O A0h R: +xxxx xxx1: Memory or parity error? +0xxx xxxx: Coprocessor installed? +*/ + case 0xA0: + if(!epoch->parityenabled) + ret &= 0xfe; + else + ret = epoch->parityerror & 1; + if (fpu_type == FPU_NONE) + ret |= 0x80; + break; + case 0xA1: /* High address where memory error occured */ + ret = epoch->parityerroraddr; + break; +/* +I/O A2h R: +xxxx 0x0x: Color CRT +xxxx 1x0x: Mono 24 CRT ? +xxxx xx1x: 16 pixel CRT +xx1x xxxx: No hard drive +x1xx xxxx: No floppy drive +1xxx xxxx: No (bootable?) hard drive +*/ + case 0xA2: + ret = 0xA8;/* Mono 24 */ + // ret = 0xA8;/* Mono 16 */ + break; +/* +I/O A3h R: +xxxx x001: Main RAM 256 KB? +xxxx x011: Main RAM 384 KB? +xxxx x111: Main RAM 512 KB? +xxxx x000: Main RAM 640 KB? +xxxx 1xxx: Serial port 3f8h +xxx1 xxxx: Serial port 2f8h +*/ + case 0xA3: + ret = 0x08; + if (mem_size < 384) + ret |= 0x07; + else if (mem_size < 512) + ret |= 0x06; + else if (mem_size < 640) + ret |= 0x04; + break; + case 0xA4: + ret = 0; + break; + case 0xA5: + ret = 0x08; /* Bit 3: Keyboard connected? */ + break; + // case 0x164: + // switch (epoch->fontcard.portdata) { + // case 0x16A: + // ret = 0xFD; + // break; + // case 0x168: + // ret = 0xFE; + // break; + // } + // break; + default: + break; + } + epoch_log("%04X:%04X I/O In %02X: %02X\n", cs >> 4, cpu_state.pc, port, ret); + return ret; +} + +static void +epoch_misc_out(uint16_t port, uint8_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + pit_intf_t *pit_intf = &pit_devs[0]; + + // dev->regs[port & 0x0007] = val; + // epoch_log("%04X:%04X I/O Out %02X: %02X\n AX=%04X BX=%04X CX=%04X DX=%04X ES=%04X DI=%04X DS=%04X SI=%04X\n", + // cs >> 4, cpu_state.pc, port, val, AX, BX, CX, DX, ES, DI, DS, SI); + if(port != 0x44) + epoch_log("%04X:%04X I/O Out %02X: %02X\n", cs >> 4, cpu_state.pc, port, val); + + switch (port) { + case 0x44: + for (uint8_t i = 0; i < 3; i++) { + pit_intf->set_gate(pit_intf->data, i, val & 1); + } + break; +/* +I/O A0h W: +x1xx xxxx: Enable parity update (Disable this -> Write data -> Enable this -> Read data, causes NMI) +1xxx xxxx: Enable NMI check +*/ + case 0xA0: + nmi_mask = val & 0x80; + epoch->parityenabled = val & 0x40; /* 1 = Enable read/write with parity */ + break; + case 0xA1: + /* Diagnostics LED (used by debug card module) */ + break; + case 0xA2: + /* Reset memory error bit */ + epoch->parityerror = 0; + break; + // case 0x160 ... 0x16A: + // mem_mapping_enable(&epoch->fontcard.map); + // epoch->fontcard.portdata = port; + // break; + case 0x310 ... 0x312: + epoch->lowmemorydisabled = 0; + epoch_log("Low memory enabled\n"); + break; + case 0x314 ... 0x316: + epoch->lowmemorydisabled = 1; + epoch_log("Low memory disabled\n"); + break; + } +} +typedef struct epochkbd_t { + int want_irq; + int blocked; + + uint8_t pa; + uint8_t pb; + uint8_t clock; + uint8_t key_waiting; + uint8_t reset_step; + + pc_timer_t send_delay_timer; +} epochkbd_t; + +static uint8_t key_queue[16]; +static int key_queue_start = 0; +static int key_queue_end = 0; + +static void +kbd_epoch_poll(void *priv) +{ + epochkbd_t *kbd = (epochkbd_t *) priv; + + timer_advance_u64(&kbd->send_delay_timer, 1000 * TIMER_USEC); + + if (kbd->pb & 0x04) + return; + + if (kbd->want_irq) { + kbd->want_irq = 0; + kbd->pa = kbd->key_waiting; + kbd->pb &= 0xF7; + kbd->blocked = 1; + picint(EPOCH_IRQ3_BIT); + epoch_log("epochkbd: kbd_poll(): keyboard_xt : take IRQ\n"); + } + + if ((key_queue_start != key_queue_end) && !kbd->blocked) { + kbd->key_waiting = key_queue[key_queue_start]; + epoch_log("epochkbd: reading %02X from the key queue at %i\n", + kbd->key_waiting, key_queue_start); + key_queue_start = (key_queue_start + 1) & 0x0f; + kbd->want_irq = 1; + } +} + +static void +kbd_epoch_adddata_process(uint16_t val, void (*adddata)(uint16_t val)) +{ + // uint8_t num_lock = 0; + // uint8_t shift_states = 0; + + if (!adddata) + return; + + // keyboard_get_states(NULL, &num_lock, NULL, NULL); + // shift_states = keyboard_get_shift() & STATE_LSHIFT; + + // /* If NumLock is on, invert the left shift state so we can always check for + // the the same way flag being set (and with NumLock on that then means it + // is actually *NOT* set). */ + // if (num_lock) + // shift_states ^= STATE_LSHIFT; + + adddata(val); +} + +static void +kbd_epoch_adddata(uint16_t val) +{ + key_queue[key_queue_end] = val; + epoch_log("XTkbd: %02X added to key queue at %i\n", + val, key_queue_end); + key_queue_end = (key_queue_end + 1) & 0x0f; +} + +static void +kbd_adddata_ex(uint16_t val) +{ + if (val < 0x100) + kbd_epoch_adddata_process(val, kbd_epoch_adddata); +} + +static void +kbd_write(uint16_t port, uint8_t val, void *priv) +{ + epochkbd_t *kbd = (epochkbd_t *) priv; + uint8_t new_clock; + epoch_log("%04X:%04X epochkbd: Port %04X out: %02X\n", cs >> 4, cpu_state.pc, port, val); + + switch (port) { + case 0x61: /* Keyboard Control Register (aka Port B) */ + if (val & 0x08) { + new_clock = !(val & 0x04); + if (kbd->clock && new_clock) { + key_queue_start = key_queue_end = 0; + kbd->want_irq = 0; + kbd->blocked = 0; + kbd->reset_step = 0; + /* Specific 5556 keyboards send three bytes of identification code, + but this simply sends AAh that can pass the IPL and DOS K3.4 init. */ + kbd_epoch_adddata(0xaa); + } else if (!(kbd->pb & 0x08)) { + kbd->pa = 0; + kbd->blocked = 0; + } + } + + kbd->pb = val; + if (kbd->pb & 0x08) + kbd->clock = !!(kbd->pb & 0x04); + ppi.pb = val; + + timer_process(); + + speaker_update(); + + speaker_gated = val & 2; + speaker_enable = val & 2; + + if (speaker_enable) + was_speaker_enable = 1; + pit_devs[0].set_gate(pit_devs[0].data, TIMER_CTR_2, val & 2); + + break; + + default: + break; + } +} + +static uint8_t +kbd_read(uint16_t port, void *priv) +{ + epochkbd_t *kbd = (epochkbd_t *) priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x60: /* Keyboard Data Register (aka Port A) */ + ret = kbd->pa; + break; + + case 0x61: /* Keyboard Control Register (aka Port B) */ + /* Bit 3 and 2: Keyboard Data and Clk line ? */ + if (kbd->reset_step < 18) { + ret &= 0xf3; + if (kbd->reset_step & 1) + ret |= 0x04; + switch (kbd->reset_step) { /* AAh (1010 1010) in serial data */ + case 3: + case 7: + case 11: + case 15: + ret |= 0x00; + break; + default: + ret |= 0x08; + break; + } + kbd->reset_step += 1; + } + /* Bit 1: Timer 2 (Speaker) out state */ + if (pit_devs[0].get_outlevel(pit_devs[0].data, TIMER_CTR_2) && speaker_enable) + ret &= 0xfd;/* 1111 1101 */ + else + ret |= 0x02; + break; + + default: + break; + } + // epoch_log("%04X:%04X epochkbd: Port %04X in : %02X BX:%04x\n", cs >> 4, cpu_state.pc, port, ret, BX); + + return ret; +} + +static void +kbd_reset(void *priv) +{ + epochkbd_t *kbd = (epochkbd_t *) priv; + + kbd->want_irq = 0; + kbd->blocked = 0; + kbd->pa = 0x00; + kbd->pb = 0x00; + + keyboard_scan = 1; + + key_queue_start = 0; + key_queue_end = 0; +} + +static void * +kbd_init(const device_t *info) +{ + epochkbd_t *kbd; + + kbd = (epochkbd_t *) calloc(1, sizeof(epochkbd_t)); + + io_sethandler(0x0060, 4, + kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); + keyboard_send = kbd_adddata_ex; + kbd_reset(kbd); + + key_queue_start = key_queue_end = 0; + + timer_add(&kbd->send_delay_timer, kbd_epoch_poll, kbd, 1); + + keyboard_set_table(scancode_set8a); + keyboard_mode = 0x8a; + + return kbd; +} + +static void +kbd_close(void *priv) +{ + epochkbd_t *kbd = (epochkbd_t *) priv; + + /* Stop the timer. */ + timer_disable(&kbd->send_delay_timer); + + /* Disable scanning. */ + keyboard_scan = 0; + + keyboard_send = NULL; + + io_removehandler(0x0060, 2, + kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); + + free(kbd); +} + +static const device_t kbc_epoch_device = { + .name = "IBM 5550 Keyboard Controller", + .internal_name = "kbc_epoch", + .flags = 0, + .local = 0, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +static void +epoch_nvr_time_set(uint8_t *regs, struct tm *tm) +{ + regs[epoch_nvr_SECOND1] = tm->tm_sec % 10; + regs[epoch_nvr_SECOND10] = (tm->tm_sec / 10); + regs[epoch_nvr_MINUTE1] = (tm->tm_min % 10); + regs[epoch_nvr_MINUTE10] = (tm->tm_min / 10); + regs[epoch_nvr_HOUR1] = (tm->tm_hour % 10); + regs[epoch_nvr_HOUR10] = (tm->tm_hour / 10); + regs[epoch_nvr_WEEKDAY] = tm->tm_wday; + regs[epoch_nvr_DAY1] = (tm->tm_mday % 10); + regs[epoch_nvr_DAY10] = (tm->tm_mday / 10); + regs[epoch_nvr_MONTH1] = ((tm->tm_mon + 1) % 10); + regs[epoch_nvr_MONTH10] = ((tm->tm_mon + 1) / 10); + regs[epoch_nvr_YEAR1] = (tm->tm_year % 10); + regs[epoch_nvr_YEAR10] = ((tm->tm_year % 100) / 10); +} + +/* Get the chip time. */ +#define nibbles(a) (regs[(a##1)] + 10 * regs[(a##10)]) +static void +epoch_nvr_time_get(uint8_t *regs, struct tm *tm) +{ + tm->tm_sec = nibbles(epoch_nvr_SECOND); + tm->tm_min = nibbles(epoch_nvr_MINUTE); + tm->tm_hour = nibbles(epoch_nvr_HOUR); + tm->tm_wday = regs[epoch_nvr_WEEKDAY]; + tm->tm_mday = nibbles(epoch_nvr_DAY); + tm->tm_mon = (nibbles(epoch_nvr_MONTH) - 1); + tm->tm_year = (nibbles(epoch_nvr_YEAR)); +} + +/* This is called every second through the NVR/RTC hook. */ +static void +epoch_nvr_tick(nvr_t *nvr) +{ + struct tm tm; + if (!(nvr->regs[epoch_nvr_CONTROL] & 0x40)) { + /* Get the current time from the internal clock. */ + nvr_time_get(&tm); + /* Update registers with current time. */ + epoch_nvr_time_set(nvr->regs, &tm); + } +} + +static void +epoch_nvr_start(nvr_t *nvr) +{ + struct tm tm; + /* Initialize the internal and chip times. */ + if (time_sync & TIME_SYNC_ENABLED) { + /* Use the internal clock's time. */ + nvr_time_get(&tm); + epoch_nvr_time_set(nvr->regs, &tm); + } else { + /* Set the internal clock from the chip time. */ + epoch_nvr_time_get(nvr->regs, &tm); + nvr_time_set(&tm); + } +} + +/* Write to one of the chip registers. */ +static void +epoch_nvr_write(uint16_t port, uint8_t val, void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + int addr = 0; + + switch (port) { + case 0x360: + epoch->nvrctrl = val; + addr = val & 0xf; + if (val & 0x20) { /* Write */ + if (addr >= 0x8 && (epoch->nvr.regs[addr] != val)) + nvr_dosave = 1; + epoch->nvr.regs[addr] = epoch->nvrdata; + } + break; + case 0x361: + if(epoch->nvrctrl & 0x40) /* Is the access enabled? */ + epoch->nvrdata = val; + break; + } + // epoch_log("%04X:%04X I/O Out %02X: %02X\n", cs >> 4, cpu_state.pc, port, val); +} + +/* Read from one of the chip registers. */ +static uint8_t +epoch_nvr_read(uint16_t port, void *priv) +{ + const epoch_t *epoch = (epoch_t *) priv; + + switch (port) { + case 0x360: + return epoch->nvrctrl; + break; + case 0x361: + if(epoch->nvrctrl & 0x40) /* Is the access enabled? */ + return (epoch->nvr.regs[(epoch->nvrctrl & 0xf)]); + break; + } + return EPOCH_INVALIDACCESS8; +} + +/* Reset the RTC registers to a default state. */ +static void +epoch_nvr_reset(nvr_t *nvr) +{ + /* Clear the NVRAM. */ + memset(nvr->regs, 0xff, nvr->size); + /* Reset the RTC registers. */ + memset(nvr->regs, 0x00, 0xc); + nvr->regs[epoch_nvr_CONTROL] = 0; +} + +static void +epoch_nvr_init(epoch_t *epoch, int size) +{ + nvr_t* nvr = &epoch->nvr; + /* This is machine specific. */ + nvr->size = size; + nvr->irq = -1; + /* Set up any local handlers here. */ + nvr->reset = epoch_nvr_reset; + nvr->start = epoch_nvr_start; + nvr->tick = epoch_nvr_tick; + /* Initialize the actual NVR. */ + nvr_init(nvr); + io_sethandler(0x0360, 2, + epoch_nvr_read, NULL, NULL, epoch_nvr_write, NULL, NULL, epoch); +} + +static uint8_t ibm5550_attr_mono[16] = +{ + 0,6,6,62,0,0,0,0,0,0,0,0,0,0,0,0 +}; + +// static uint8_t ps55_attr_color[16] = /* for video mode 0eh color character */ +// { +// 0x00,0x38,0x24,0x3c,0x12,0x3a,0x36,0x3e,0x09,0x39,0x2d,0x3d,0x1b,0x3b,0x3f,0x3f +// }; + +/* 12-bit DAC color palette for IBMJ Display Adapter with color monitor */ +static uint8_t ps55_palette_color[64][3] = { + { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x2A }, { 0x00, 0x2A, 0x00 }, { 0x00, 0x2A, 0x2A }, + { 0x2A, 0x00, 0x00 }, { 0x2A, 0x00, 0x2A }, { 0x2A, 0x2A, 0x00 }, { 0x2A, 0x2A, 0x2A }, + { 0x00, 0x00, 0x15 }, { 0x00, 0x00, 0x3F }, { 0x00, 0x2A, 0x15 }, { 0x00, 0x2A, 0x3F }, + { 0x2A, 0x00, 0x15 }, { 0x2A, 0x00, 0x3F }, { 0x2A, 0x2A, 0x15 }, { 0x2A, 0x2A, 0x3F }, + { 0x00, 0x15, 0x00 }, { 0x00, 0x15, 0x2A }, { 0x00, 0x3F, 0x00 }, { 0x00, 0x3F, 0x2A }, + { 0x2A, 0x15, 0x00 }, { 0x2A, 0x15, 0x2A }, { 0x2A, 0x3F, 0x00 }, { 0x2A, 0x3F, 0x2A }, + { 0x00, 0x15, 0x15 }, { 0x00, 0x15, 0x3F }, { 0x00, 0x3F, 0x15 }, { 0x00, 0x3F, 0x3F }, + { 0x2A, 0x15, 0x15 }, { 0x2A, 0x15, 0x3F }, { 0x2A, 0x3F, 0x15 }, { 0x2A, 0x3F, 0x3F }, + { 0x15, 0x00, 0x00 }, { 0x15, 0x00, 0x2A }, { 0x15, 0x2A, 0x00 }, { 0x15, 0x2A, 0x2A }, + { 0x3F, 0x00, 0x00 }, { 0x3F, 0x00, 0x2A }, { 0x3F, 0x2A, 0x00 }, { 0x3F, 0x2A, 0x2A }, + { 0x15, 0x00, 0x15 }, { 0x15, 0x00, 0x3F }, { 0x15, 0x2A, 0x15 }, { 0x15, 0x2A, 0x3F }, + { 0x3F, 0x00, 0x15 }, { 0x3F, 0x00, 0x3F }, { 0x3F, 0x2A, 0x15 }, { 0x3F, 0x2A, 0x3F }, + { 0x15, 0x15, 0x00 }, { 0x15, 0x15, 0x2A }, { 0x15, 0x3F, 0x00 }, { 0x15, 0x3F, 0x2A }, + { 0x3F, 0x15, 0x00 }, { 0x3F, 0x15, 0x2A }, { 0x3F, 0x3F, 0x00 }, { 0x3F, 0x3F, 0x2A }, + { 0x15, 0x15, 0x15 }, { 0x15, 0x15, 0x3F }, { 0x15, 0x3F, 0x15 }, { 0x15, 0x3F, 0x3F }, + { 0x3F, 0x15, 0x15 }, { 0x3F, 0x15, 0x3F }, { 0x3F, 0x3F, 0x15 }, { 0x3F, 0x3F, 0x3F } +}; + +static video_timings_t timing_epoch_vid = +{ .type = VIDEO_ISA, .write_b = 8, .write_w = 8, .write_l = 16, .read_b = 8, .read_w = 8, .read_l = 16 }; + +static void +epoch_reset(void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + + epoch->parityerror = 0; + epoch->parityenabled = 1; + epoch->lowmemorydisabled = 1; + epoch->crtioenabled = 0; + // epoch->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ + epoch->crtc[LC_HORIZONTAL_TOTAL] = 103; /* Horizontal Total */ + epoch->crtc[LC_VERTICAL_TOTAL] = 26; /* Vertical Total (These two must be set before the timer starts.) */ + epoch->crtmode = 0x08; + epoch->vram_display_mask = EPOCH_MASK_CRAM; + // epoch->plane_mask = 1; + epoch->oddeven = 0; + // epoch->memaddr_latch = 0; + // epoch->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ + // epoch->attr_palette_enable = 0; /* disable attribute generator */ + + // epoch->attrc[LV_PAS_STATUS_CNTRL] = 0; + // epoch->attrc[LV_PANNING] = 0; + + /* Set internal color palette registers */ + for (uint16_t i = 0; i < 16; i++) { + epoch->egapal[i] = ibm5550_attr_mono[i]; + } + /* Set color palette for video output */ + for (uint16_t i = 0; i < 64; i++) { + epoch->vgapal[i].r = ps55_palette_color[i & 0x3F][0]; + epoch->vgapal[i].g = ps55_palette_color[i & 0x3F][1]; + epoch->vgapal[i].b = ps55_palette_color[i & 0x3F][2]; + epoch->pallook[i] = makecol32((epoch->vgapal[i].r & 0x3f) * 4, (epoch->vgapal[i].g & 0x3f) * 4, (epoch->vgapal[i].b & 0x3f) * 4); + } + + // mem_mapping_disable(&epoch->fontcard.map); + + epoch_log("epoch_reset done.\n"); +} + +/* +//[Font ROM Map (DA1)] +//Bank 0 +// 0000-581Fh Pointers (Low) for each character font? +// 5820-7FFFh Pointers (High) for each character font? +// 8000- * h Font Data +*/ +// static void +// epoch_video_load_font(char *fname, epoch_t *epoch) +// { +// uint8_t buf; +// uint64_t fsize; +// if (!fname) +// return; +// if (*fname == '\0') +// return; +// FILE *mfile = rom_fopen(fname, "rb"); +// if (!mfile) { +// // da2_log("MSG: Can't open binary ROM font file: %s\n", fname); +// return; +// } +// fseek(mfile, 0, SEEK_END); +// fsize = ftell(mfile); /* get filesize */ +// fseek(mfile, 0, SEEK_SET); +// if (fsize > EPOCH_FONTROM_SIZE) { +// fsize = EPOCH_FONTROM_SIZE; /* truncate read data */ +// // da2_log("MSG: The binary ROM font is truncated: %s\n", fname); +// // fclose(mfile); +// // return 1; +// } +// uint32_t j = 0; +// while (ftell(mfile) < fsize) { +// (void) !fread(&buf, sizeof(uint8_t), 1, mfile); +// epoch->fontcard.rom[j] = buf; +// j++; +// } +// fclose(mfile); +// return; +// } + +// static void +// epoch_font_writeb(uint32_t addr, uint8_t val, void *priv) +// { +// epoch_t *epoch = (epoch_t *) priv; +// epoch->fontcard.bank = val; +// // if ((addr & ~0xfff) != 0xE0000) return; +// epoch_log("cw %04X %02X %04X %04X %04X %04X\n", addr, val, DS, SI, ES, DI); +// } +// static uint8_t +// epoch_font_readb(uint32_t addr, void *priv) +// { +// epoch_t *epoch = (epoch_t *) priv; +// uint32_t readaddr = epoch->fontcard.bank; +// addr &= EPOCH_FONTROM_MASK; +// readaddr *= 0xc000;/* xxx x000 0000 0000 0000 (8000h) */ +// readaddr += addr; +// if (readaddr >= EPOCH_FONTROM_SIZE) +// return EPOCH_INVALIDACCESS8; +// // epoch_log("cr %X %x %04X %04X %04X %04X\n", readaddr, epoch->fontcard.rom[readaddr], DS, SI, ES, DI); +// // if(epoch->vram[addr] == 0xcb) +// // epoch_log("CB %04X:%04X %04X:%04X>%04X:%04X\n", cs >> 4, cpu_state.pc, DS, SI,ES,DI); +// return epoch->fontcard.rom[readaddr]; +// } +static void * +epoch_init(UNUSED(const device_t *info)) +{ + epoch_t *epoch = calloc(1, sizeof(epoch_t)); + video_inform(VIDEO_FLAG_TYPE_NONE, &timing_epoch_vid); + video_update_timing(); + + epoch->dispontime = 1000ull << 32; + epoch->dispofftime = 1000ull << 32; + // epoch->changedvram = calloc(1, (EPOCH_MASK_VRAMPLANE + 1) >> 9); /* XX000h */ + changeframecount = 3; + + epoch->vram = calloc(1, 256* 1024); + epoch->cram = calloc(1, 4 * 1024); + // epoch->fontcard.rom = calloc(1, EPOCH_FONTROM_SIZE); + //epoch_video_load_font("roms/machines/ibm5550/GEN1FONT.BIN", epoch); + + epoch->epochconst = (uint64_t) ((cpuclock / EPOCH_PIXELCLOCK) * (double) (1ull << 32)); + + epoch_reset(epoch); + + mem_mapping_add(&epoch->cmap, 0xE0000, 0x1000, epoch_cram_readb, epoch_cram_readw, NULL, + epoch_cram_writeb, epoch_cram_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); + mem_mapping_add(&epoch->vmap, 0xA0000, 0x40000, epoch_vram_readb, epoch_vram_readw, NULL, + epoch_vram_writeb, epoch_vram_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); + // mem_mapping_add(&epoch->fontcard.map, 0xF0000, 0xC000, epoch_font_readb, NULL, NULL, + // epoch_font_writeb, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, epoch); + + mem_mapping_disable(&epoch->cmap); + mem_mapping_disable(&epoch->vmap); + // mem_mapping_disable(&epoch->fontcard.map); + mem_mapping_add(&epoch->paritymap, 0, 0xA0000, epoch_parity_readb, epoch_parity_readw, NULL, + epoch_parity_writeb, epoch_parity_writew, NULL, NULL, MEM_MAPPING_CACHE, epoch); + + io_sethandler(0x03d0, 0x0020, epoch_inb, epoch_inw, NULL, epoch_outb, epoch_outw, NULL, epoch); + + io_sethandler(0x44, 0x0001, + epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch); + io_sethandler(0xA0, 0x0005, + epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch); + io_sethandler(0x310, 0x0008, + epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch); + // io_sethandler(0x160, 0x0010, + // epoch_misc_in, NULL, NULL, epoch_misc_out, NULL, NULL, epoch); + + timer_add(&epoch->timer, epoch_poll, epoch, 1); + + epoch_nvr_init(epoch, 17); + + return epoch; +} + +static void +epoch_close(void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + + /* dump mem for debug */ +#ifdef ENABLE_EPOCH_LOG + FILE *fp; + fp = fopen("epoch_cram.dmp", "wb"); + if (fp != NULL) { + fwrite(epoch->cram, EPOCH_SIZE_CRAM, 1, fp); + fclose(fp); + } + fp = fopen("epoch_vram.dmp", "wb"); + if (fp != NULL) { + fwrite(epoch->vram, EPOCH_SIZE_VRAM, 1, fp); + fclose(fp); + } + // fp = fopen("epoch_attrpal.dmp", "wb"); + // if (fp != NULL) { + // fwrite(epoch->attrc, 32, 1, fp); + // fclose(fp); + // } + fp = fopen("epoch_daregs.txt", "w"); + if (fp != NULL) { + // for (uint8_t i = 0; i < 0x10; i++) + // fprintf(fp, "3e1(ioctl) %02X: %4X %d\n", i, epoch->ioctl[i], epoch->ioctl[i]); + // for (uint8_t i = 0; i < 0x20; i++) + // fprintf(fp, "3e3(fctl) %02X: %4X %d\n", i, epoch->fctl[i], epoch->fctl[i]); + for (uint8_t i = 0; i < 0x20; i++) + fprintf(fp, "3e5(crtc) %02X: %4X %d\n", i, epoch->crtc[i], epoch->crtc[i]); + // for (uint8_t i = 0; i < 0x40; i++) + // fprintf(fp, "3e8(attr) %02X: %4X %d\n", i, epoch->attrc[i], epoch->attrc[i]); + // for (uint8_t i = 0; i < 0x10; i++) + // fprintf(fp, "3eb(gcr) %02X: %4X\n", i, epoch->gdcreg[i]); + // for (uint8_t i = 0; i < 0x20; i++) { + // fprintf(fp, "vp %02X: %4X %4X %4X %4X\n", i, + // epoch->crtc_vpreg[0 + i], epoch->crtc_vpreg[0x20 + i], epoch->crtc_vpreg[0x40 + i], epoch->crtc_vpreg[0x60 + i]); + // } + fclose(fp); + } + fp = fopen("ram_low.dmp", "wb"); + if (fp != NULL) { + fwrite(ram, 0x40000, 1, fp); + fclose(fp); + } + epoch_log("closed %04X:%04X AX=%04X BX=%04X CX=%04X DX=%04X ES=%04X DI=%04X DS=%04X SI=%04X\n", + cs >> 4, cpu_state.pc, AX, BX, CX, DX, ES, DI, DS, SI); + epoch_log("PIC IRR=%02X ISR=%02X IMR=%02X ICW1=%02X ICW2=%02X ICW3=%02X ICW4=%02X OCW2=%02X OCW3=%02X\n", + pic.irr, pic.isr, pic.imr, pic.icw1, pic.icw2, pic.icw3, pic.icw4, pic.ocw2, pic.ocw3); +#endif + free(epoch->cram); + free(epoch->vram); + // free(epoch->fontcard.rom); + // free(epoch->changedvram); + free(epoch); +} + +static void +epoch_speed_changed(void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + epoch->epochconst = (uint64_t) ((cpuclock / EPOCH_PIXELCLOCK) * (double) (1ull << 32)); + epoch_recalctimings(epoch); +} + +static void +epoch_force_redraw(void *priv) +{ + epoch_t *epoch = (epoch_t *) priv; + epoch->fullchange = changeframecount; +} + +static const device_t epoch_device = { + .name = "IBM 5550 Video Controller (Epoch)", + .internal_name = "ibm5550vid", + .flags = DEVICE_ISA, + .local = 0, + .init = epoch_init, + .close = epoch_close, + .reset = epoch_reset, + .available = NULL, + .speed_changed = epoch_speed_changed, + .force_redraw = epoch_force_redraw, + .config = NULL +}; + +static void +pit_irq6_timer(int new_out, int old_out, UNUSED(void *priv)) +{ + // epoch_log("%04X:%04X IRQ6 Timer triggered.\n", cs >> 4, cpu_state.pc); + if (new_out && !old_out) + picint(EPOCH_IRQ6_BIT); + + if (!new_out) + picintc(EPOCH_IRQ6_BIT); +} + +static pit_t * +pit_ibm5550_init(void) +{ + void *pit; + + pit_intf_t *pit_intf = &pit_devs[0]; + + pit = device_add(&i8253_device); + *pit_intf = pit_classic_intf; + + pit_intf->data = pit; + + for (uint8_t i = 0; i < 3; i++) { + pit_intf->set_gate(pit_intf->data, i, 1); + pit_intf->set_using_timer(pit_intf->data, i, 1); + } + + pit_intf->set_out_func(pit_intf->data, TIMER_CTR_1, pit_irq6_timer); + pit_intf->set_out_func(pit_intf->data, TIMER_CTR_0, pit_refresh_timer_xt); + pit_intf->set_out_func(pit_intf->data, TIMER_CTR_2, pit_speaker_timer); + pit_intf->set_load_func(pit_intf->data, TIMER_CTR_2, speaker_set_count); + + pit_intf->set_gate(pit_intf->data, TIMER_CTR_2, 0); + + return pit; +} + +int +machine_xt_ibm5550_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ibm5550/ipl5550.rom", + 0x000fc000, 16384, 0); + + if (bios_only || !ret) + return ret; + + device_add(&fdc_xt_5550_device); + + device_add(&kbc_epoch_device); + + pic_init(); + dma_init(); + pit_ibm5550_init(); + nmi_mask = 0; + + device_add(&epoch_device); + + device_add(&lpt_port_device); + serial_t *uart = device_add(&ns8250_device); + serial_setup(uart, 0x3f8, 1);/* Use IRQ 1 */ + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index c64e15af8..c67a22c04 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -3033,6 +3033,49 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[8086] IBM Multistation 5550", + .internal_name = "ibm5550", + .type = MACHINE_TYPE_8086, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_ibm5550_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8086, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_VIDEO_FIXED | MACHINE_KEYBOARD, + .ram = { + .min = 256, + .max = 640, + .step = 128 + }, + .nvrmask = 15, + .jumpered_ecp_dma = 0, + .default_jumpered_ecp_dma = -1, + .kbc_device = NULL, + .kbc_params = 0x00000000, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .kbd_device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 286 AT machines */ /* Has IBM AT KBC firmware. */ @@ -5468,6 +5511,50 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has unknown KBC firmware */ + { + .name = "[HT18] Tandy 1000 RSX", + .internal_name = "tandy1000rsx", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_HT18, + .init = machine_at_tandy1000rsx_init, + .p1_handler = machine_generic_p1_handler, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_GAMEPORT, + .ram = { + .min = 1024, + .max = 9216, + .step = 512 + }, + .nvrmask = 127, + .jumpered_ecp_dma = 0, + .default_jumpered_ecp_dma = -1, + .kbc_device = &kbc_at_device, + .kbc_params = 0x00000000, + .kbc_p1 = 0x000004f0, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .kbd_device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &gd5402_onboard_device, + .snd_device = NULL, + .net_device = NULL + }, /* Most likely has a Phoenix MultiKey/42 keyboard controller. */ { .name = "[Intel 82335] ADI 386SX", diff --git a/src/network/net_switch.c b/src/network/net_switch.c index d29513f74..ced2f0392 100644 --- a/src/network/net_switch.c +++ b/src/network/net_switch.c @@ -49,10 +49,11 @@ #include <86box/config.h> #include <86box/net_event.h> #include <86box/bswap.h> +#include #define SWITCH_PKT_BATCH NET_QUEUE_LEN -#define SWITCH_MULTICAST_GROUP 0xefff5656 /* 239.255.86.86 */ +#define SWITCH_MULTICAST_GROUP 0xefff5056 /* 239.255.80.86 */ #define SWITCH_MULTICAST_PORT 8086 enum { @@ -80,6 +81,8 @@ typedef struct net_switch_t { net_switch_hostaddr_t *hostaddrs; uint16_t port_out; + uint8_t secret_enabled; + uint8_t secret_hash[32]; uint8_t promisc; union { uint8_t mac_addr[6]; @@ -123,6 +126,15 @@ net_switch_in_available(void *priv) net_event_set(&netswitch->tx_event); } +static void +net_switch_secret_hash(const char *secret, uint8_t *hash) +{ + SHA3Context cx; + SHA3Init(&cx, 256); + SHA3Update(&cx, (const uint8_t *)secret, strlen(secret)); + memcpy(hash, SHA3Final(&cx), 32); +} + static unsigned int net_switch_add_hostaddr(net_switch_t *netswitch, net_switch_sockaddr_t *addr, net_switch_sockaddr_t *broadcast, net_switch_sockaddr_t *netmask, unsigned int flags) { @@ -186,10 +198,12 @@ net_switch_add_hostaddr(net_switch_t *netswitch, net_switch_sockaddr_t *addr, ne } /* Join IPv4 multicast group. */ - struct ip_mreq mreq = { - .imr_multiaddr = { .s_addr = htonl(SWITCH_MULTICAST_GROUP) }, - .imr_interface = { .s_addr = hostaddr->addr.sin.sin_addr.s_addr } - }; + struct ip_mreq mreq = { .imr_interface = { .s_addr = hostaddr->addr.sin.sin_addr.s_addr } }; + if (netswitch->secret_enabled) + mreq.imr_multiaddr.s_addr = htonl(SWITCH_MULTICAST_GROUP); + else + mreq.imr_multiaddr.s_addr = htonl(SWITCH_MULTICAST_GROUP + 0x600); // 239.255.86.86 + if (setsockopt(netswitch->socket_rx, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq)) < 0) { netswitch_log("Network Switch: could not join multicast group on interface %s\n", buf); goto broadcast; @@ -374,16 +388,35 @@ net_switch_thread(void *priv) packets = network_tx_popv(netswitch->card, netswitch->pkt_tx_v, SWITCH_PKT_BATCH); if (!(net_cards_conf[netswitch->card->card_num].link_state & NET_LINK_DOWN)) { for (int i = 0; i < packets; i++) { + int orig_len = netswitch->pkt_tx_v[i].len; + int send_len = orig_len; + uint8_t augmented[sizeof(netswitch->secret_hash) + NET_MAX_FRAME]; + if (netswitch->secret_enabled) { + send_len = orig_len + sizeof(netswitch->secret_hash); + + /* Build header with secret hash */ + uint8_t *hdr = augmented; + memcpy(hdr, netswitch->secret_hash, sizeof(netswitch->secret_hash)); + memcpy(augmented + sizeof(netswitch->secret_hash), + netswitch->pkt_tx_v[i].data, orig_len); + } + #define MAC_FORMAT "(%02X:%02X:%02X:%02X:%02X:%02X -> %02X:%02X:%02X:%02X:%02X:%02X)" -#define MAC_FORMAT_ARGS(p) (p)[6], (p)[7], (p)[8], (p)[9], (p)[10], (p)[11], (p)[0], (p)[1], (p)[2], (p)[3], (p)[4], (p)[5] +#define MAC_FORMAT_NOSECRET_ARGS(p) (p)[6], (p)[7], (p)[8], (p)[9], (p)[10], (p)[11], (p)[0], (p)[1], (p)[2], (p)[3], (p)[4], (p)[5] +#define MAC_FORMAT_ARGS(p) (p)[38], (p)[39], (p)[40], (p)[41], (p)[42], (p)[43], (p)[32], (p)[33], (p)[34], (p)[35], (p)[36], (p)[37] netswitch_log("Network Switch: sending %d-byte packet " MAC_FORMAT "\n", - netswitch->pkt_tx_v[i].len, MAC_FORMAT_ARGS(netswitch->pkt_tx_v[i].data)); + netswitch->pkt_tx_v[i].len, + netswitch->secret_enabled ? MAC_FORMAT_ARGS(netswitch->pkt_tx_v[i].data) + : MAC_FORMAT_NOSECRET_ARGS(netswitch->pkt_tx_v[i].data)); /* Send through all known host interfaces. */ for (net_switch_hostaddr_t *hostaddr = netswitch->hostaddrs; hostaddr; hostaddr = hostaddr->next) - sendto(hostaddr->socket_tx, - (char *) netswitch->pkt_tx_v[i].data, netswitch->pkt_tx_v[i].len, 0, - &hostaddr->addr_tx.sa, sizeof(hostaddr->addr_tx.sa)); + if (netswitch->secret_enabled) + sendto(hostaddr->socket_tx, (char *)augmented, send_len, 0, + &hostaddr->addr_tx.sa, sizeof(hostaddr->addr_tx.sa)); + else + sendto(hostaddr->socket_tx, (char *)netswitch->pkt_tx_v[i].data, + send_len, 0, &hostaddr->addr_tx.sa, sizeof(hostaddr->addr_tx.sa)); } } netswitch->during_tx = 0; @@ -406,10 +439,32 @@ net_switch_thread(void *priv) } if (pfd[NET_EVENT_RX].revents & POLLIN) { #endif - len = recv(netswitch->socket_rx, (char *) netswitch->pkt.data, NET_MAX_FRAME, 0); - if (len < 12) { - netswitch_log("Network Switch: recv error (%d)\n", len); - } else if ((AS_U64(netswitch->pkt.data[6]) & le64_to_cpu(0xffffffffffffULL)) == netswitch->mac_addr_u64) { + if (netswitch->secret_enabled) { + len = recv(netswitch->socket_rx, (char *) netswitch->pkt.data, NET_MAX_FRAME + sizeof(netswitch->secret_hash), 0); + if (len < sizeof(netswitch->secret_hash) + 12) { + netswitch_log("Network Switch: recv error (%d)\n", len); + continue; + } + + if (memcmp(netswitch->pkt.data, netswitch->secret_hash, sizeof(netswitch->secret_hash)) != 0) { + /* This packet contains a different secret hash, ignore it. */ + continue; + } else { + memmove(netswitch->pkt.data, + netswitch->pkt.data + sizeof(netswitch->secret_hash), + len - sizeof(netswitch->secret_hash)); + len = len - sizeof(netswitch->secret_hash); + netswitch->pkt.len = len; + } + } else { + len = recv(netswitch->socket_rx, (char *) netswitch->pkt.data, NET_MAX_FRAME, 0); + if (len < 12) { + netswitch_log("Network Switch: recv error (%d)\n", len); + continue; + } + } + + if ((AS_U64(netswitch->pkt.data[netswitch->secret_enabled ? 38 : 6]) & le64_to_cpu(0xffffffffffffULL)) == netswitch->mac_addr_u64) { /* A packet we've sent has looped back, drop it. */ } else if (!(net_cards_conf[netswitch->card->card_num].link_state & NET_LINK_DOWN) && (netswitch->promisc || /* promiscuous mode? */ (netswitch->pkt.data[0] & 1) || /* broadcast packet? */ @@ -443,13 +498,20 @@ net_switch_init(const netcard_t *card, const uint8_t *mac_addr, void *priv, char { netcard_conf_t *netcard = (netcard_conf_t *) priv; - netswitch_log("Network Switch: initializing with group %d...\n", netcard->switch_group); - net_switch_t *netswitch = calloc(1, sizeof(net_switch_t)); memcpy(netswitch->mac_addr, mac_addr, sizeof(netswitch->mac_addr)); netswitch->card = (netcard_t *) card; netswitch->promisc = !!netcard->promisc_mode; + if (netcard->secret[0] != '\0') { + uint8_t temp[32]; + net_switch_secret_hash((const uint8_t *)netcard->secret, (uint8_t *) temp); + memcpy(netswitch->secret_hash, temp, 32); + netswitch->secret_enabled = 1; + } else { + netswitch->secret_enabled = 0; + } + /* Initialize receive socket. */ netswitch->socket_rx = socket(AF_INET, SOCK_DGRAM, 0); if (netswitch->socket_rx < 0) { @@ -473,7 +535,7 @@ net_switch_init(const netcard_t *card, const uint8_t *mac_addr, void *priv, char val = 0; setsockopt(netswitch->socket_rx, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &val, sizeof(val)); - netswitch->port_out = htons(SWITCH_MULTICAST_PORT - NET_SWITCH_GRP_MIN + netcard->switch_group); + netswitch->port_out = htons(SWITCH_MULTICAST_PORT); struct sockaddr_in addr = { .sin_family = AF_INET, .sin_addr = { .s_addr = htonl(INADDR_ANY) }, diff --git a/src/pit.c b/src/pit.c index 7c58a4b67..5a8078c97 100644 --- a/src/pit.c +++ b/src/pit.c @@ -420,6 +420,15 @@ pit_ctr_get_count(void *data, int counter_id) return (uint16_t) ctr->l; } +int +pit_ctr_get_outlevel(void *data, int counter_id) +{ + const pit_t *pit = (pit_t *) data; + const ctr_t *ctr = &pit->counters[counter_id]; + + return (int) ctr->out; +} + void pit_ctr_set_load_func(void *data, int counter_id, void (*func)(uint8_t new_m, int new_count)) { @@ -1208,6 +1217,11 @@ pit_set_clock(uint32_t clock) CGACONST = (uint64_t) ((cpuclock / (157500000.0 / 88.0)) * (double) (1ULL << 32)); #endif } + + if (machines[machine].init == machine_xt_ibm5550_init) { + PITCONSTD = (cpuclock / 2000000.0); /* CLK input 2.0 MHz */ + PITCONST = (uint64_t) (PITCONSTD * (double) (1ULL << 32)); + } ISACONST = (1ULL << 32ULL); } @@ -1263,6 +1277,7 @@ const pit_intf_t pit_classic_intf = { .read = &pit_read, .write = &pit_write, .get_count = &pit_ctr_get_count, + .get_outlevel = &pit_ctr_get_outlevel, .set_gate = &pit_ctr_set_gate, .set_using_timer = &pit_ctr_set_using_timer, .set_out_func = &pit_ctr_set_out_func, diff --git a/src/printer/prt_cpmap.c b/src/printer/prt_cpmap.c index 370e258ce..37243f0db 100644 --- a/src/printer/prt_cpmap.c +++ b/src/printer/prt_cpmap.c @@ -1,75 +1,24 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. * - * Various ASCII to Unicode maps, for the various codepages. + * This file is part of the 86Box distribution. * - * Authors: Michael Drüing, - * Fred N. van Kempen, + * Code page to Unicode mapping + * for a generic ESC/P 2 dot-matrix printer. * - * Based on code by Frederic Weymann (originally for DosBox.) + * Authors: Lili Kurek, * - * Copyright 2018 Michael Drüing. - * Copyright 2018 Fred N. van Kempen. + * Based on code by Frederic Weymann (originally for DOSBox.) * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * Copyright 2025-2026 Lili Kurek. */ #include #include -#include -#include -#include -#include <86box/86box.h> -#include <86box/plat.h> -#include <86box/printer.h> -static const uint16_t cp437Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp437Map[128] = { 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, @@ -88,23 +37,7 @@ static const uint16_t cp437Map[256] = { 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; -static const uint16_t cp737Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp737Map[128] = { 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, @@ -123,23 +56,7 @@ static const uint16_t cp737Map[256] = { 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; -static const uint16_t cp775Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp775Map[128] = { 0x0106, 0x00fc, 0x00e9, 0x0101, 0x00e4, 0x0123, 0x00e5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012b, 0x0179, 0x00c4, 0x00c5, 0x00c9, 0x00e6, 0x00c6, 0x014d, 0x00f6, 0x0122, 0x00a2, 0x015a, @@ -158,23 +75,7 @@ static const uint16_t cp775Map[256] = { 0x00b0, 0x2219, 0x00b7, 0x00b9, 0x00b3, 0x00b2, 0x25a0, 0x00a0 }; -static const uint16_t cp850Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp850Map[128] = { 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, @@ -193,23 +94,7 @@ static const uint16_t cp850Map[256] = { 0x00b0, 0x00a8, 0x00b7, 0x00b9, 0x00b3, 0x00b2, 0x25a0, 0x00a0 }; -static const uint16_t cp852Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp852Map[128] = { 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x016f, 0x0107, 0x00e7, 0x0142, 0x00eb, 0x0150, 0x0151, 0x00ee, 0x0179, 0x00c4, 0x0106, 0x00c9, 0x0139, 0x013a, 0x00f4, 0x00f6, 0x013d, 0x013e, 0x015a, @@ -228,23 +113,7 @@ static const uint16_t cp852Map[256] = { 0x00b0, 0x00a8, 0x02d9, 0x0171, 0x0158, 0x0159, 0x25a0, 0x00a0 }; -static const uint16_t cp855Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp855Map[128] = { 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, 0x0459, 0x0409, 0x045a, 0x040a, 0x045b, 0x040b, 0x045c, 0x040c, @@ -263,23 +132,7 @@ static const uint16_t cp855Map[256] = { 0x042d, 0x0449, 0x0429, 0x0447, 0x0427, 0x00a7, 0x25a0, 0x00a0 }; -static const uint16_t cp857Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp857Map[128] = { 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x0131, 0x00c4, 0x00c5, 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, @@ -298,23 +151,7 @@ static const uint16_t cp857Map[256] = { 0x00b0, 0x00a8, 0x00b7, 0x00b9, 0x00b3, 0x00b2, 0x25a0, 0x00a0 }; -static const uint16_t cp860Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp860Map[128] = { 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e3, 0x00e0, 0x00c1, 0x00e7, 0x00ea, 0x00ca, 0x00e8, 0x00cd, 0x00d4, 0x00ec, 0x00c3, 0x00c2, 0x00c9, 0x00c0, 0x00c8, 0x00f4, 0x00f5, 0x00f2, 0x00da, 0x00f9, @@ -333,23 +170,7 @@ static const uint16_t cp860Map[256] = { 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; -static const uint16_t cp861Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp861Map[128] = { 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00d0, 0x00f0, 0x00de, 0x00c4, 0x00c5, 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00fe, 0x00fb, 0x00dd, @@ -368,23 +189,7 @@ static const uint16_t cp861Map[256] = { 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; -static const uint16_t cp862Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp862Map[128] = { 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, @@ -403,23 +208,7 @@ static const uint16_t cp862Map[256] = { 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; -static const uint16_t cp863Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp863Map[128] = { 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00c2, 0x00e0, 0x00b6, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x2017, 0x00c0, 0x00a7, 0x00c9, 0x00c8, 0x00ca, 0x00f4, 0x00cb, 0x00cf, 0x00fb, 0x00f9, @@ -438,23 +227,7 @@ static const uint16_t cp863Map[256] = { 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; -static const uint16_t cp864Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x066a, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp864Map[128] = { 0x00b0, 0x00b7, 0x2219, 0x221a, 0x2592, 0x2500, 0x2502, 0x253c, 0x2524, 0x252c, 0x251c, 0x2534, 0x2510, 0x250c, 0x2514, 0x2518, 0x03b2, 0x221e, 0x03c6, 0x00b1, 0x00bd, 0x00bc, 0x2248, 0x00ab, @@ -473,23 +246,7 @@ static const uint16_t cp864Map[256] = { 0xfed5, 0xfef5, 0xfef6, 0xfedd, 0xfed9, 0xfef1, 0x25a0, 0x00a0 }; -static const uint16_t cp865Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp865Map[128] = { 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, @@ -508,23 +265,7 @@ static const uint16_t cp865Map[256] = { 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0 }; -static const uint16_t cp866Map[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, +static const uint16_t cp866Map[128] = { 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, @@ -570,7 +311,7 @@ static const struct { void select_codepage(uint16_t code, uint16_t *curmap) { - uint16_t i = 0; + uint8_t i = 0; const uint16_t *map_to_use; map_to_use = maps[0].map; @@ -583,6 +324,9 @@ select_codepage(uint16_t code, uint16_t *curmap) i++; } - for (uint16_t j = 0; j < 256; j++) - curmap[j] = map_to_use[j]; + for (i = 0; i < 128; ++i) + curmap[i] = i; + + for (; i != 0; ++i) + curmap[i] = map_to_use[i - 128]; } diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index 7164ec835..5a507ad30 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -1,63 +1,30 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. * - * Implementation of the Generic ESC/P 2 Dot-Matrix printer. + * This file is part of the 86Box distribution. * - * Authors: Michael Drüing, - * Fred N. van Kempen, + * Implementation of a generic ESC/P 2 dot-matrix printer. * - * Based on code by Frederic Weymann (originally for DosBox.) + * Authors: Lili Kurek, * - * Copyright 2018-2019 Michael Drüing. - * Copyright 2019 Fred N. van Kempen. + * Based on code by Frederic Weymann (originally for DOSBox.) * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * Copyright 2025-2026 Lili Kurek. */ + #include +#include #include #include -#include -#include -#include #include #include #include FT_FREETYPE_H #define HAVE_STDARG_H #include <86box/86box.h> -#include <86box/device.h> #include "cpu.h" -#include <86box/machine.h> #include <86box/timer.h> #include <86box/mem.h> #include <86box/rom.h> @@ -79,6 +46,11 @@ enum { LANG_ESCP2 }; +enum { + QUALITY_DRAFT = 0, + QUALITY_LQ +}; + enum { PAPER_LETTER = 0, PAPER_A4, @@ -88,7 +60,7 @@ enum { /* Default page values (for now.) */ #define COLOR_BLACK 7 << 5 -#define PAGE_CPI 10.0 /* standard310 cpi */ +#define PAGE_CPI 10.0 /* standard 10 cpi */ #define PAGE_LPI 6.0 /* standard 6 lpi */ /* FreeType library handles - global so they can be shared. */ @@ -106,19 +78,19 @@ enum { }; /* Font styles. */ -#define STYLE_PROP 0x0001 -#define STYLE_CONDENSED 0x0002 -#define STYLE_BOLD 0x0004 -#define STYLE_DOUBLESTRIKE 0x0008 -#define STYLE_DOUBLEWIDTH 0x0010 -#define STYLE_ITALICS 0x0020 -#define STYLE_UNDERLINE 0x0040 -#define STYLE_SUPERSCRIPT 0x0080 -#define STYLE_SUBSCRIPT 0x0100 -#define STYLE_STRIKETHROUGH 0x0200 -#define STYLE_OVERSCORE 0x0400 -#define STYLE_DOUBLEWIDTHONELINE 0x0800 -#define STYLE_DOUBLEHEIGHT 0x1000 +#define STYLE_PROP 0x0002 +#define STYLE_CONDENSED 0x0004 +#define STYLE_BOLD 0x0008 +#define STYLE_DOUBLESTRIKE 0x0010 +#define STYLE_DOUBLEWIDTH 0x0020 +#define STYLE_ITALICS 0x0040 +#define STYLE_UNDERLINE 0x0080 +#define STYLE_SUPERSCRIPT 0x0100 +#define STYLE_SUBSCRIPT 0x0200 +#define STYLE_STRIKETHROUGH 0x0400 +#define STYLE_OVERSCORE 0x0800 +#define STYLE_DOUBLEWIDTHONELINE 0x1000 +#define STYLE_DOUBLEHEIGHT 0x2000 /* Underlining styles. */ #define SCORE_NONE 0x00 @@ -127,10 +99,6 @@ enum { #define SCORE_SINGLEBROKEN 0x05 #define SCORE_DOUBLEBROKEN 0x06 -/* Print quality. */ -#define QUALITY_DRAFT 0x01 -#define QUALITY_LQ 0x02 - /* Typefaces. */ enum { TYPEFACE_ROMAN = 0, @@ -151,8 +119,8 @@ enum { /* Some helper macros. */ #define PARAM16(x) (dev->esc_parms[x + 1] * 256 + dev->esc_parms[x]) -#define PIXX ((unsigned) floor(dev->curr_x * dev->dpi + 0.5)) -#define PIXY ((unsigned) floor(dev->curr_y * dev->dpi + 0.5)) +#define PIXX ((unsigned) round(dev->curr_x * dev->dpi)) +#define PIXY ((unsigned) round(dev->curr_y * dev->dpi)) typedef struct psurface_t { int8_t dirty; /* has the page been printed on? */ @@ -179,6 +147,8 @@ typedef struct escp_t { char page_fn[260]; uint8_t color; + bool dc1_selected; + /* page data (TODO: make configurable) */ double page_width; /* all in inches */ double page_height; @@ -204,24 +174,25 @@ typedef struct escp_t { /* bit graphics data */ uint16_t bg_h_density; /* in dpi */ uint16_t bg_v_density; /* in dpi */ - int8_t bg_adjacent; /* print adjacent pixels (ignored) */ + int8_t bg_adjacent; /* print adjacent pixels */ uint8_t bg_bytes_per_column; uint16_t bg_remaining_bytes; /* #bytes left before img is complete */ uint8_t bg_column[6]; /* #bytes of the current and last col */ + uint8_t bg_previous[6]; // for non-adjacent pixels in graphics mode uint8_t bg_bytes_read; /* #bytes read so far for current col */ /* handshake data */ uint8_t data; - uint8_t ack; - uint8_t select; - uint8_t busy; - uint8_t int_pending; - uint8_t error; - uint8_t autofeed; + bool ack; + bool select; + bool busy; + bool int_pending; + bool error; + bool autofeed; /* ESC command data */ - int8_t esc_seen; /* set to 1 if an ESC char was seen */ - int8_t fss_seen; + bool esc_seen; /* set if an ESC char was seen */ + bool fss_seen; uint16_t esc_pending; /* in which ESC command are we */ uint8_t esc_parms_req; uint8_t esc_parms_curr; @@ -266,7 +237,7 @@ typedef struct escp_t { PALETTE palcol; - uint8_t auto_lf; + bool auto_lf; } escp_t; /* Codepage table, needed for ESC t ( */ @@ -327,18 +298,13 @@ static const uint16_t intCharSets[15][12] = { }; #ifdef ENABLE_ESCP_LOG -int escp_do_log = ENABLE_ESCP_LOG; - static void escp_log(const char *fmt, ...) { va_list ap; - - if (escp_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); } #else # define escp_log(fmt, ...) @@ -381,7 +347,7 @@ pulse_timer(void *priv) escp_t *dev = (escp_t *) priv; if (dev->ack) { - dev->ack = 0; + dev->ack = false; lpt_irq(dev->lpt, 1); } @@ -402,13 +368,11 @@ timeout_timer(void *priv) static void fill_palette(uint8_t redmax, uint8_t greenmax, uint8_t bluemax, uint8_t colorID, escp_t *dev) { - uint8_t colormask; + const uint8_t colormask = colorID <<= 5; - double red = (double) redmax / (double) 30.9; - double green = (double) greenmax / (double) 30.9; - double blue = (double) bluemax / (double) 30.9; - - colormask = colorID <<= 5; + const double red = (double) redmax / (double) 30.9; + const double green = (double) greenmax / (double) 30.9; + const double blue = (double) bluemax / (double) 30.9; for (uint8_t i = 0; i < 32; i++) { dev->palcol[i + colormask].r = 255 - (uint8_t) floor(red * (double) i); @@ -427,7 +391,7 @@ update_font(escp_t *dev) double vpoints = 10.5; /* We need the FreeType library. */ - if (ft_lib == NULL) + if (!ft_lib) return; /* Release current font if we have one. */ @@ -561,9 +525,10 @@ reset_printer(escp_t *dev) dev->bottom_margin = dev->page_height - 1.0 / 36.0; /* TODO: these should be configurable. */ dev->color = COLOR_BLACK; + dev->dc1_selected = true; dev->curr_x = dev->curr_y = 0.0; - dev->esc_seen = 0; - dev->fss_seen = 0; + dev->esc_seen = false; + dev->fss_seen = false; dev->esc_pending = 0; dev->esc_parms_req = dev->esc_parms_curr = 0; dev->lpi = PAGE_LPI; @@ -571,7 +536,7 @@ reset_printer(escp_t *dev) dev->cpi = PAGE_CPI; dev->curr_char_table = 1; dev->font_style = 0; - dev->print_quality = QUALITY_DRAFT; + dev->print_quality = device_get_config_int("quality"); dev->extra_intra_space = 0.0; dev->print_upper_control = 1; dev->bg_remaining_bytes = 0; @@ -601,7 +566,7 @@ reset_printer(escp_t *dev) dev->num_horizontal_tabs = 32; dev->num_vertical_tabs = -1; - if (dev->page != NULL) + if (dev->page) dev->page->dirty = 0; escp_log("ESC/P: width=%.1fin,height=%.1fin dpi=%i cpi=%i lpi=%i\n", @@ -612,7 +577,7 @@ reset_printer(escp_t *dev) static void reset_printer_hard(escp_t *dev) { - dev->ack = 0; + dev->ack = false; timer_disable(&dev->pulse_timer); timer_stop(&dev->timeout_timer); reset_printer(dev); @@ -777,6 +742,8 @@ setup_bit_image(escp_t *dev, uint8_t density, uint16_t num_columns) escp_log("ESC/P: Unsupported bit image density %d.\n", density); break; } + for (uint8_t i = 0; i < dev->bg_bytes_per_column; ++i) + dev->bg_previous[i] = 0; dev->bg_remaining_bytes = num_columns * dev->bg_bytes_per_column; dev->bg_bytes_read = 0; @@ -802,7 +769,7 @@ process_char(escp_t *dev, uint8_t ch) dev->esc_pending = ch; if (dev->fss_seen) dev->esc_pending |= 0x800; - dev->esc_seen = dev->fss_seen = 0; + dev->esc_seen = dev->fss_seen = false; dev->esc_parms_curr = 0; escp_log("Command pending=%02x, font path=%s\n", dev->esc_pending, dev->fontpath); @@ -1168,24 +1135,11 @@ process_char(escp_t *dev, uint8_t ch) case '!': /* master select */ dev->cpi = (dev->esc_parms[0]) & 0x01 ? 12.0 : 10.0; - /* Reset first seven bits. */ - dev->font_style &= 0xFF80; - if (dev->esc_parms[0] & 0x02) - dev->font_style |= STYLE_PROP; - if (dev->esc_parms[0] & 0x04) - dev->font_style |= STYLE_CONDENSED; - if (dev->esc_parms[0] & 0x08) - dev->font_style |= STYLE_BOLD; - if (dev->esc_parms[0] & 0x10) - dev->font_style |= STYLE_DOUBLESTRIKE; - if (dev->esc_parms[0] & 0x20) - dev->font_style |= STYLE_DOUBLEWIDTH; - if (dev->esc_parms[0] & 0x40) - dev->font_style |= STYLE_ITALICS; - if (dev->esc_parms[0] & 0x80) { + /* Reset first seven style bits (starting from two as CPI had one). */ + dev->font_style &= 0xFF01; + dev->font_style |= dev->esc_parms[0]; + if (dev->esc_parms[0] & 0x80) dev->font_score = SCORE_SINGLE; - dev->font_style |= STYLE_UNDERLINE; - } dev->hmi = -1; dev->multipoint_mode = 0; @@ -1267,6 +1221,10 @@ process_char(escp_t *dev, uint8_t ch) dev->print_upper_control = 0; break; + case '8': // disable + case '9': // enable paper-out sensor + // We don't have real paper, ignore. + case '<': /* unidirectional mode (one line) */ /* We don't have a print head, so just * ignore this. */ @@ -1408,7 +1366,7 @@ process_char(escp_t *dev, uint8_t ch) break; case 'T': /* cancel superscript/subscript printing */ - dev->font_style &= 0xFFFF - STYLE_SUPERSCRIPT - STYLE_SUBSCRIPT; + dev->font_style &= ~(STYLE_SUPERSCRIPT | STYLE_SUBSCRIPT); update_font(dev); break; @@ -1736,7 +1694,7 @@ process_char(escp_t *dev, uint8_t ch) } if (dev->font_style & STYLE_DOUBLEWIDTHONELINE) { - dev->font_style &= 0xFFFF - STYLE_DOUBLEWIDTHONELINE; + dev->font_style &= ~STYLE_DOUBLEWIDTHONELINE; update_font(dev); } return 1; @@ -1783,8 +1741,8 @@ process_char(escp_t *dev, uint8_t ch) return 1; case 0x11: /* select printer (DC1) */ - /* Ignore. */ - return 0; + dev->dc1_selected = true; + return 1; case 0x12: /* cancel condensed printing (DC2) */ dev->hmi = -1; @@ -1793,7 +1751,7 @@ process_char(escp_t *dev, uint8_t ch) return 1; case 0x13: /* deselect printer (DC3) */ - /* Ignore. */ + dev->dc1_selected = false; return 1; case 0x14: /* cancel double-width printing (one line) (DC4) */ @@ -1806,13 +1764,13 @@ process_char(escp_t *dev, uint8_t ch) return 1; case 0x1b: /* ESC */ - dev->esc_seen = 1; + dev->esc_seen = true; return 1; case 0x1c: /* FS (IBM Proprinter II) TODO: Make an IBM printer. */ if (dev->lang == LANG_ESCP2) { - dev->fss_seen = 1; + dev->fss_seen = true; return 1; } @@ -1831,7 +1789,7 @@ blit_glyph(escp_t *dev, unsigned destx, unsigned desty, int8_t add) uint8_t *dst; /* check if freetype is available */ - if (ft_lib == NULL) + if (!ft_lib) return; for (unsigned int y = 0; y < bitmap->rows; y++) { @@ -1879,10 +1837,6 @@ draw_hline(escp_t *dev, unsigned from_x, unsigned to_x, unsigned y, int8_t broke static void print_bit_graph(escp_t *dev, uint8_t ch) { - uint8_t pixel_w; /* width of the "pixel" */ - uint8_t pixel_h; /* height of the "pixel" */ - double old_y; - dev->bg_column[dev->bg_bytes_read++] = ch; dev->bg_remaining_bytes--; @@ -1890,16 +1844,18 @@ print_bit_graph(escp_t *dev, uint8_t ch) if (dev->bg_bytes_read < dev->bg_bytes_per_column) return; - old_y = dev->curr_y; + /* vertical density is how big the dot is + * (horziontal / vertical / 2) is how many middle points between two full dots are + * if horizontal < vertical, this means a column is printed multiple times + */ + uint8_t dot_size_x; + const uint8_t dot_size_y = round((double) dev->dpi / (double) dev->bg_v_density); + if (dev->bg_h_density < dev->bg_v_density) + dot_size_x = round((double) dev->dpi / (double) dev->bg_h_density); + else + dot_size_x = dot_size_y; - pixel_w = 1; - pixel_h = 1; - - if (dev->bg_adjacent) { - /* if page DPI is bigger than bitgraphics DPI, drawn pixels get "bigger" */ - pixel_w = dev->dpi / dev->bg_h_density > 0 ? dev->dpi / dev->bg_h_density : 1; - pixel_h = dev->dpi / dev->bg_v_density > 0 ? dev->dpi / dev->bg_v_density : 1; - } + const double old_y = dev->curr_y; for (uint8_t i = 0; i < dev->bg_bytes_per_column; i++) { /* for each byte */ @@ -1908,11 +1864,21 @@ print_bit_graph(escp_t *dev, uint8_t ch) break; /* for each bit */ if (dev->bg_column[i] & j) { - /* draw a "pixel" */ - for (uint8_t xx = 0; xx < pixel_w; xx++) { - for (uint8_t yy = 0; yy < pixel_h; yy++) { - if (((PIXX + xx) < (unsigned) dev->page->w) && ((PIXY + yy) < (unsigned) dev->page->h)) - *((uint8_t *) dev->page->pixels + (PIXX + xx) + (PIXY + yy) * dev->page->pitch) |= (dev->color | 0x1f); + if (!(dev->bg_adjacent) && (dev->bg_previous[i] & j)) { + dev->bg_column[i] &= ~j; + dev->curr_y += 1.0 / (double) dev->bg_v_density; + continue; + } + /* draw a dot */ + for (uint8_t xx = 0; xx < dot_size_x; ++xx) { + if ((PIXX + xx) >= (unsigned) dev->page->w) + break; + + for (uint8_t yy = 0; yy < dot_size_y; ++yy) { + if ((PIXY + yy) >= (unsigned) dev->page->h) + break; + + *((uint8_t *) dev->page->pixels + (PIXX + xx) + (PIXY + yy) * dev->page->pitch) |= (dev->color | 0x1f); } } } @@ -1921,6 +1887,8 @@ print_bit_graph(escp_t *dev, uint8_t ch) } } + memcpy(dev->bg_previous, dev->bg_column, dev->bg_bytes_per_column * sizeof(uint8_t)); + /* Mark page dirty. */ dev->page->dirty = 1; @@ -1943,16 +1911,18 @@ handle_char(escp_t *dev, uint8_t ch) uint16_t line_y; double x_advance; - if (dev->page == NULL) + if (!(dev->page)) return; /* MSB mode */ - if (dev->msb != 255) { - if (dev->msb == 0) - ch &= 0x7f; - else if (dev->msb == 1) - ch |= 0x80; - } + if (dev->msb == 0) + ch &= 0x7f; + else if (dev->msb == 1) + ch |= 0x80; + // else it's neutral at 255 + + if (!(dev->dc1_selected) && ch != 0x11) + return; if (dev->bg_remaining_bytes > 0) { print_bit_graph(dev, ch); @@ -1970,7 +1940,7 @@ handle_char(escp_t *dev, uint8_t ch) } /* We cannot print if we have no font loaded. */ - if (dev->fontface == NULL) + if (!(dev->fontface)) return; if (ch == 0x01) @@ -2055,7 +2025,7 @@ write_data(uint8_t val, void *priv) { escp_t *dev = (escp_t *) priv; - if (dev == NULL) + if (!dev) return; dev->data = val; @@ -2066,7 +2036,7 @@ strobe(uint8_t old, uint8_t val, void *priv) { escp_t *dev = (escp_t *) priv; - if (dev == NULL) + if (!dev) return; /* Data is strobed to the parallel printer on the falling edge of the @@ -2083,7 +2053,7 @@ strobe(uint8_t old, uint8_t val, void *priv) #endif } /* ACK it, will be read on next READ STATUS. */ - dev->ack = 1; + dev->ack = true; timer_set_delay_u64(&dev->pulse_timer, ISACONST); timer_on_auto(&dev->timeout_timer, 5000000.0); @@ -2095,17 +2065,17 @@ write_ctrl(uint8_t val, void *priv) { escp_t *dev = (escp_t *) priv; - if (dev == NULL) + if (!dev) return; if (val & 0x08) { /* SELECT */ /* select printer */ - dev->select = 1; + dev->select = true; } if ((val & 0x04) && !(dev->ctrl & 0x04)) { /* reset printer */ - dev->select = 0; + dev->select = false; reset_printer_hard(dev); } @@ -2124,7 +2094,7 @@ write_ctrl(uint8_t val, void *priv) #endif } /* ACK it, will be read on next READ STATUS. */ - dev->ack = 1; + dev->ack = true; timer_set_delay_u64(&dev->pulse_timer, ISACONST); timer_on_auto(&dev->timeout_timer, 5000000.0); @@ -2163,11 +2133,11 @@ escp_init(const device_t *info) escp_t *dev = NULL; /* Initialize FreeType. */ - if (ft_lib == NULL) { + if (!ft_lib) { if (FT_Init_FreeType(&ft_lib)) { pclog("ESC/P: FT_Init_FreeType failed\n"); ft_lib = NULL; - return (NULL); + return(NULL); } } @@ -2186,7 +2156,7 @@ escp_init(const device_t *info) ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_ESCP_ERROR_TITLE), plat_get_string(STRING_ESCP_ERROR_DESC)); free(dev); - return (NULL); + return(NULL); } /* Create the full path for the page images. */ @@ -2229,14 +2199,13 @@ escp_init(const device_t *info) memset(dev->page->pixels, 0x00, (size_t) dev->page->pitch * dev->page->h); /* Initialize parameters. */ + /* 0 = all white needed for logic 000 */ for (uint8_t i = 0; i < 32; i++) { dev->palcol[i].r = 255; dev->palcol[i].g = 255; dev->palcol[i].b = 255; } - /* 0 = all white needed for logic 000 */ - fill_palette(0, 0, 0, 1, dev); /* 1 = magenta* 001 */ fill_palette(0, 255, 0, 1, dev); /* 2 = cyan* 010 */ @@ -2254,7 +2223,7 @@ escp_init(const device_t *info) dev->color = COLOR_BLACK; dev->fontface = 0; - dev->autofeed = 0; + dev->autofeed = false; reset_printer(dev); @@ -2272,15 +2241,15 @@ escp_close(void *priv) { escp_t *dev = (escp_t *) priv; - if (dev == NULL) + if (!dev) return; - if (dev->page != NULL) { + if (dev->page) { /* Print last page if it contains data. */ if (dev->page->dirty) dump_page(dev); - if (dev->page->pixels != NULL) + if (dev->page->pixels) free(dev->page->pixels); free(dev->page); } @@ -2290,11 +2259,6 @@ escp_close(void *priv) } // clang-format off -#if 0 -static const device_config_t lpt_prt_escp_config[] = { - { .name = "", .description = "", .type = CONFIG_END } -}; -#endif static const device_config_t lpt_prt_escp_config[] = { { .name = "language", @@ -2332,6 +2296,21 @@ static const device_config_t lpt_prt_escp_config[] = { }, .bios = { { 0 } } }, + { + .name = "quality", + .description = "Quality", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Draft", .value = QUALITY_DRAFT }, + { .description = "(Near) Letter", .value = QUALITY_LQ }, + { .description = "" } + }, + .bios = { { 0 } } + }, { .name = "auto_lf", .description = "Auto LF", diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index c62c18ea8..8bcc5c794 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -2832,7 +2832,7 @@ msgstr "" msgid "Remote Switch" msgstr "" -msgid "Switch:" +msgid "Shared secret:" msgstr "" msgid "Hub Mode" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index 0c1c8ac89..813b82dcb 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -2838,8 +2838,8 @@ msgstr "Commutador local" msgid "Remote Switch" msgstr "Commutador remot" -msgid "Switch:" -msgstr "Commutador:" +msgid "Shared secret:" +msgstr "Secret compartit:" msgid "Hub Mode" msgstr "Modalitat de concentrador" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 1df82475f..f27ac9d3c 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -2838,8 +2838,8 @@ msgstr "Lokální switch" msgid "Remote Switch" msgstr "Vzdálený switch" -msgid "Switch:" -msgstr "Switch:" +msgid "Shared secret:" +msgstr "Sdílené tajemství:" msgid "Hub Mode" msgstr "Režim hubu" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index d0e649bc2..fc201c303 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -2838,8 +2838,8 @@ msgstr "Lokaler Schalter" msgid "Remote Switch" msgstr "Entfernter Schalter" -msgid "Switch:" -msgstr "Schalter:" +msgid "Shared secret:" +msgstr "Gemeinsames Geheimnis:" msgid "Hub Mode" msgstr "Hub-Modus" diff --git a/src/qt/languages/el-GR.po b/src/qt/languages/el-GR.po index 1442183df..7465743e0 100644 --- a/src/qt/languages/el-GR.po +++ b/src/qt/languages/el-GR.po @@ -2883,8 +2883,8 @@ msgstr "Τοπικός Διακόπτης" msgid "Remote Switch" msgstr "Απομακρυσμένος Διακόπτης" -msgid "Switch:" -msgstr "Διακόπτης:" +msgid "Shared secret:" +msgstr "Κοινό μυστικό:" msgid "Hub Mode" msgstr "Λειτουργία Hub" diff --git a/src/qt/languages/en-GB.po b/src/qt/languages/en-GB.po index fdc71fcb1..b2dc80dd7 100644 --- a/src/qt/languages/en-GB.po +++ b/src/qt/languages/en-GB.po @@ -15,6 +15,9 @@ msgstr "&RGB Greyscale" msgid "Generic RGBI color monitor" msgstr "Generic RGBI colour monitor" +msgid "Grayscale &conversion type" +msgstr "Greyscale &conversion type" + msgid "Time synchronization" msgstr "Time synchronisation" @@ -28,7 +31,7 @@ msgid "Failed to initialize network driver" msgstr "Failed to initialise network driver" msgid "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." -msgstr "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behaviour will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." +msgstr "Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager.\n\nNo further updates will be provided through WinBox, and you may encounter incorrect behaviour should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behaviour will be closed as invalid.\n\nGo to 86box.net for a list of other managers you can use." msgid "Appl&y fullscreen stretch mode when maximized" msgstr "Appl&y fullscreen stretch mode when maximised" @@ -78,9 +81,18 @@ msgstr "Enhanced Colour - Enhanced Mode (5154/ECD)" msgid "Gray" msgstr "Grey" +msgid "Grayscale" +msgstr "Greyscale" + msgid "Color" msgstr "Colour" +msgid "Color Interlaced" +msgstr "Colour Interlaced" + +msgid "Color Non-Interlaced" +msgstr "Colour Non-Interlaced" + msgid "Failed to initialize Vulkan renderer." msgstr "Failed to initialise Vulkan renderer." diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index af2e1e75e..54e3d2079 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -2838,8 +2838,8 @@ msgstr "Conmutador local" msgid "Remote Switch" msgstr "Conmutador remoto" -msgid "Switch:" -msgstr "Conmutador:" +msgid "Shared secret:" +msgstr "Secreto compartido:" msgid "Hub Mode" msgstr "Modo de concentrador" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 2351f1afa..9d4e84f39 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -2838,8 +2838,8 @@ msgstr "Paikallinen kytkin" msgid "Remote Switch" msgstr "Etäkytkin" -msgid "Switch:" -msgstr "Kytkin:" +msgid "Shared secret:" +msgstr "Jaettu salaisuus:" msgid "Hub Mode" msgstr "Hubitila" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 42f1a8f40..453b52de4 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -2838,8 +2838,8 @@ msgstr "Commutateur local" msgid "Remote Switch" msgstr "Commutateur distant" -msgid "Switch:" -msgstr "Commutateur :" +msgid "Shared secret:" +msgstr "Secret partagé:" msgid "Hub Mode" msgstr "Mode concentrateur" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 32aaf1cf7..f1e8e3688 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -2840,8 +2840,8 @@ msgstr "Lokalni prekidač" msgid "Remote Switch" msgstr "Udaljeni prekidač" -msgid "Switch:" -msgstr "Prekidač:" +msgid "Shared secret:" +msgstr "Zajednička tajna:" msgid "Hub Mode" msgstr "Način čvorišta" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index f46d09159..71fc69bce 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -2838,8 +2838,8 @@ msgstr "Commutatore locale" msgid "Remote Switch" msgstr "Commutatore remoto" -msgid "Switch:" -msgstr "Commutatore:" +msgid "Shared secret:" +msgstr "Segreto condiviso:" msgid "Hub Mode" msgstr "Modalità Hub" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 027b05204..487e5e297 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -2839,8 +2839,8 @@ msgstr "ローカルスイッチ" msgid "Remote Switch" msgstr "リモートスイッチ" -msgid "Switch:" -msgstr "スイッチ:" +msgid "Shared secret:" +msgstr "共有秘密:" msgid "Hub Mode" msgstr "ハブモード" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index a46dc07c7..cd85aec57 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -2838,8 +2838,8 @@ msgstr "로컬 스위치" msgid "Remote Switch" msgstr "원격 스위치" -msgid "Switch:" -msgstr "스위치:" +msgid "Shared secret:" +msgstr "공유 비밀:" msgid "Hub Mode" msgstr "허브 모드" diff --git a/src/qt/languages/nb-NO.po b/src/qt/languages/nb-NO.po index b22f0bf69..b8370fedb 100644 --- a/src/qt/languages/nb-NO.po +++ b/src/qt/languages/nb-NO.po @@ -2839,8 +2839,8 @@ msgstr "Lokal svitsj" msgid "Remote Switch" msgstr "Ekstern svitsj" -msgid "Switch:" -msgstr "Svitsj:" +msgid "Shared secret:" +msgstr "Delt hemmelighet:" msgid "Hub Mode" msgstr "Hub-modus" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 3ad6f4feb..e48409dcd 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -2838,8 +2838,8 @@ msgstr "Lokale Switch" msgid "Remote Switch" msgstr "Externe Switch" -msgid "Switch:" -msgstr "Switch:" +msgid "Shared secret:" +msgstr "Gedeeld geheim:" msgid "Hub Mode" msgstr "Hub-modus" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index e67ada685..e235bf995 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -2839,8 +2839,8 @@ msgstr "Switch lokalny" msgid "Remote Switch" msgstr "Switch zdalny" -msgid "Switch:" -msgstr "Switch:" +msgid "Shared secret:" +msgstr "Wspólny sekret:" msgid "Hub Mode" msgstr "Tryb hub" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 5ffbc2c72..bd95c22ce 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -2832,8 +2832,8 @@ msgstr "Switch Local" msgid "Remote Switch" msgstr "Switch Remoto" -msgid "Switch:" -msgstr "Switch:" +msgid "Shared secret:" +msgstr "Segredo compartilhado:" msgid "Hub Mode" msgstr "Modo Hub" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index 8f0f55caf..123376ee1 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -2839,8 +2839,8 @@ msgstr "Comutador local" msgid "Remote Switch" msgstr "Comutador remoto" -msgid "Switch:" -msgstr "Comutador:" +msgid "Shared secret:" +msgstr "Segredo partilhado:" msgid "Hub Mode" msgstr "Modo de concentrador" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index 9ca679356..2f272b262 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -2851,8 +2851,8 @@ msgstr "Локальный коммутатор" msgid "Remote Switch" msgstr "Удалённый коммутатор" -msgid "Switch:" -msgstr "Номер коммутатора:" +msgid "Shared secret:" +msgstr "Общий секрет:" msgid "Hub Mode" msgstr "Режим концентратора" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index a5570faeb..2de580e32 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -2838,8 +2838,8 @@ msgstr "Lokálny prepínač" msgid "Remote Switch" msgstr "Vzdialený prepínač" -msgid "Switch:" -msgstr "Prepínač:" +msgid "Shared secret:" +msgstr "Zdieľané tajomstvo:" msgid "Hub Mode" msgstr "Režim hubu" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index dfe0acbcd..bbddd9a7e 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -2840,8 +2840,8 @@ msgstr "Lokalno stikalo" msgid "Remote Switch" msgstr "Oddaljeno stikalo" -msgid "Switch:" -msgstr "Stikalo:" +msgid "Shared secret:" +msgstr "Skupna skrivnost:" msgid "Hub Mode" msgstr "Način koncentratorja" diff --git a/src/qt/languages/sv-SE.po b/src/qt/languages/sv-SE.po index 5a8c7291c..c5a09f506 100644 --- a/src/qt/languages/sv-SE.po +++ b/src/qt/languages/sv-SE.po @@ -2838,8 +2838,8 @@ msgstr "Lokal switch" msgid "Remote Switch" msgstr "Fjärr-switch" -msgid "Switch:" -msgstr "Switch:" +msgid "Shared secret:" +msgstr "Delad hemlighet:" msgid "Hub Mode" msgstr "Hubb-läge" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 510fd82f3..d113c92b8 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -2838,8 +2838,8 @@ msgstr "Yerel Switch" msgid "Remote Switch" msgstr "Uzak Switch" -msgid "Switch:" -msgstr "Switch:" +msgid "Shared secret:" +msgstr "Paylaşılan sır:" msgid "Hub Mode" msgstr "Hub Modu" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index d1964e647..3e6b695e1 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -2840,8 +2840,8 @@ msgstr "Локальний комутатор" msgid "Remote Switch" msgstr "Віддалений комутатор" -msgid "Switch:" -msgstr "Номер комутатора:" +msgid "Shared secret:" +msgstr "Спільний секрет:" msgid "Hub Mode" msgstr "Режим концентратора" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 73b59831a..4bd9d7baa 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -2839,8 +2839,8 @@ msgstr "Công tắc cục bộ" msgid "Remote Switch" msgstr "Công tắc từ xa" -msgid "Switch:" -msgstr "Công tắc:" +msgid "Shared secret:" +msgstr "Bí mật chia sẻ:" msgid "Hub Mode" msgstr "Chế độ hub" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 7e98480cd..706c7f8ad 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-01-23 17:57+0000\n" +"PO-Revision-Date: 2026-02-11 06:30+0000\n" "Last-Translator: BlueRain-debug \n" "Language-Team: Chinese (Simplified Han script) \n" @@ -2839,8 +2839,8 @@ msgstr "本地交换机" msgid "Remote Switch" msgstr "远程交换机" -msgid "Switch:" -msgstr "交换机:" +msgid "Shared secret:" +msgstr "共享密钥:" msgid "Hub Mode" msgstr "集线器模式" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 78365a911..2b2189f2c 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -2839,8 +2839,8 @@ msgstr "本地交換器" msgid "Remote Switch" msgstr "遠端交換器" -msgid "Switch:" -msgstr "交換器:" +msgid "Shared secret:" +msgstr "共用秘鑰:" msgid "Hub Mode" msgstr "集線器模式" diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index 968858dd2..c9250f44c 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -592,10 +592,10 @@ MediaMenu::cdromMount(int i, int dir, const QString &arg) if (dir > 1) filename = QString::asprintf(R"(ioctl://%s)", arg.toUtf8().data()); else if (dir == 1) - filename = QFileDialog::getExistingDirectory(parentWidget); + filename = QFileDialog::getExistingDirectory(parentWidget, QString(), getMediaOpenDirectory()); else { filename = QFileDialog::getOpenFileName(parentWidget, QString(), - QString(), + getMediaOpenDirectory(), tr("CD-ROM images") % util::DlgFilter({ "iso", "cue", "mds", "mdx" }) % tr("All files") % util::DlgFilter({ "*" }, true)); } @@ -1199,10 +1199,13 @@ MediaMenu::nicUpdateMenu(int i) QString MediaMenu::getMediaOpenDirectory() { - QString openDirectory; + static bool firstCall = true; + QString openDirectory; - if (open_dir_usr_path > 0) + if (open_dir_usr_path > 0 && firstCall) { openDirectory = QString::fromUtf8(usr_path); + firstCall = false; + } return openDirectory; } diff --git a/src/qt/qt_settingsnetwork.cpp b/src/qt/qt_settingsnetwork.cpp index 878944e60..ff933fceb 100644 --- a/src/qt/qt_settingsnetwork.cpp +++ b/src/qt/qt_settingsnetwork.cpp @@ -49,13 +49,9 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) auto *option_list_label = findChild(QString("labelOptionList%1").arg(i + 1)); auto *option_list_line = findChild(QString("lineOptionList%1").arg(i + 1)); - // Switch group - auto *switch_group_label = findChild(QString("labelSwitch%1").arg(i + 1)); - // auto *switch_group_hlayout = findChild(QString("HLayoutSwitch%1").arg(i + 1)); - // auto *switch_group_hspacer = findChild(QString("horizontalSpacerSwitch%1").arg(i + 1)); - auto *switch_group_value = findChild(QString("spinnerSwitch%1").arg(i + 1)); - switch_group_value->setMinimum(NET_SWITCH_GRP_MIN); - switch_group_value->setMaximum(NET_SWITCH_GRP_MAX); + // Shared secret + auto *secret_label = findChild(QString("labelSecret%1").arg(i + 1)); + auto *secret_value = findChild(QString("secretSwitch%1").arg(i + 1)); // Promiscuous option auto *promisc_label = findChild(QString("labelPromisc%1").arg(i + 1)); @@ -73,10 +69,8 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) // NEW STUFF // Make all options invisible by default - // Switch group - switch_group_label->setVisible(false); - switch_group_value->setVisible(false); - // switch_group_hspacer->setVisible(false); + secret_label->setVisible(false); + secret_value->setVisible(false); // Promiscuous options promisc_label->setVisible(false); @@ -142,10 +136,9 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) option_list_label->setVisible(true); option_list_line->setVisible(true); - // Switch group - switch_group_label->setVisible(true); - switch_group_value->setVisible(true); - // switch_group_hspacer->setVisible(false); + // Shared secret + secret_label->setVisible(true); + secret_value->setVisible(true); // Promiscuous options promisc_label->setVisible(true); @@ -157,10 +150,9 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) option_list_label->setVisible(true); option_list_line->setVisible(true); - // Switch group - switch_group_label->setVisible(true); - switch_group_value->setVisible(true); - // switch_group_hspacer->setVisible(false); + // Shared secret + secret_label->setVisible(true); + secret_value->setVisible(true); // Hostname hostname_label->setVisible(true); @@ -215,7 +207,7 @@ SettingsNetwork::save() cbox = findChild(QString("comboBoxIntf%1").arg(i + 1)); auto *hostname_value = findChild(QString("hostnameSwitch%1").arg(i + 1)); auto *promisc_value = findChild(QString("boxPromisc%1").arg(i + 1)); - auto *switch_group_value = findChild(QString("spinnerSwitch%1").arg(i + 1)); + auto *secret_value = findChild(QString("secretSwitch%1").arg(i + 1)); memset(net_cards_conf[i].host_dev_name, '\0', sizeof(net_cards_conf[i].host_dev_name)); if (net_cards_conf[i].net_type == NET_TYPE_PCAP) strncpy(net_cards_conf[i].host_dev_name, network_devs[cbox->currentData().toInt()].device, sizeof(net_cards_conf[i].host_dev_name) - 1); @@ -230,10 +222,12 @@ SettingsNetwork::save() else if (net_cards_conf[i].net_type == NET_TYPE_NRSWITCH) { memset(net_cards_conf[i].nrs_hostname, '\0', sizeof(net_cards_conf[i].nrs_hostname)); strncpy(net_cards_conf[i].nrs_hostname, hostname_value->text().toUtf8().constData(), sizeof(net_cards_conf[i].nrs_hostname) - 1); - net_cards_conf[i].switch_group = switch_group_value->value(); + memset(net_cards_conf[i].secret, '\0', sizeof(net_cards_conf[i].secret)); + strncpy(net_cards_conf[i].secret, secret_value->text().toUtf8().constData(), sizeof(net_cards_conf[i].secret) - 1); } else if (net_cards_conf[i].net_type == NET_TYPE_NLSWITCH) { net_cards_conf[i].promisc_mode = promisc_value->isChecked(); - net_cards_conf[i].switch_group = switch_group_value->value(); + memset(net_cards_conf[i].secret, '\0', sizeof(net_cards_conf[i].secret)); + strncpy(net_cards_conf[i].secret, secret_value->text().toUtf8().constData(), sizeof(net_cards_conf[i].secret) - 1); } } } @@ -349,13 +343,13 @@ SettingsNetwork::onCurrentMachineChanged(int machineId) } else if (net_cards_conf[i].net_type == NET_TYPE_NLSWITCH) { auto *promisc_value = findChild(QString("boxPromisc%1").arg(i + 1)); promisc_value->setCheckState(net_cards_conf[i].promisc_mode == 1 ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); - auto *switch_group_value = findChild(QString("spinnerSwitch%1").arg(i + 1)); - switch_group_value->setValue(net_cards_conf[i].switch_group); + auto *secret_value = findChild(QString("secretSwitch%1").arg(i + 1)); + secret_value->setText(net_cards_conf[i].secret); } else if (net_cards_conf[i].net_type == NET_TYPE_NRSWITCH) { auto *hostname_value = findChild(QString("hostnameSwitch%1").arg(i + 1)); hostname_value->setText(net_cards_conf[i].nrs_hostname); - auto *switch_group_value = findChild(QString("spinnerSwitch%1").arg(i + 1)); - switch_group_value->setValue(net_cards_conf[i].switch_group); + auto *secret_value = findChild(QString("secretSwitch%1").arg(i + 1)); + secret_value->setText(net_cards_conf[i].secret); } } } diff --git a/src/qt/qt_settingsnetwork.ui b/src/qt/qt_settingsnetwork.ui index 12b74004f..5f7bd316a 100644 --- a/src/qt/qt_settingsnetwork.ui +++ b/src/qt/qt_settingsnetwork.ui @@ -170,38 +170,18 @@ - + - Switch: + Shared secret: - - - - - 1 - - - 10 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + 256 + + @@ -385,38 +365,18 @@ - + - Switch: + Shared secret: - - - - - 1 - - - 10 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + 256 + + @@ -600,38 +560,18 @@ - + - Switch: + Shared secret: - - - - - 1 - - - 10 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + 256 + + @@ -815,38 +755,18 @@ - + - Switch: + Shared secret: - - - - - 1 - - - 10 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + 256 + + diff --git a/src/sound/snd_pssj.c b/src/sound/snd_pssj.c index 7de8ec824..1b10fdd8d 100644 --- a/src/sound/snd_pssj.c +++ b/src/sound/snd_pssj.c @@ -55,8 +55,10 @@ pssj_write(uint16_t port, uint8_t val, void *priv) if (!pssj->enable) timer_disable(&pssj->timer_count); sn74689_set_extra_divide(&pssj->sn76489, val & 0x40); - if (!(val & 8)) + if (!(val & 8)) { pssj->irq = 0; + picintc(1 << 7); + } pssj_update_irq(pssj); break; case 1: @@ -78,7 +80,7 @@ pssj_write(uint16_t port, uint8_t val, void *priv) break; case 3: pssj->freq = (pssj->freq & 0x0ff) | ((val & 0xf) << 8); - pssj->amplitude = val >> 4; + pssj->amplitude = (val & 0xef) >> 4; break; default: diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 872743b72..d44d9e9d8 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -45,7 +45,7 @@ # undef CLAMP #endif -#define BIOS_MACH8_ROM_PATH "roms/video/mach8/11301113140_ROM.BIN" +#define BIOS_MACH8_ROM_PATH "roms/video/mach8/11301113140_4k.BIN" static void ibm8514_accel_outb(uint16_t port, uint8_t val, void *priv); static void ibm8514_accel_outw(uint16_t port, uint16_t val, void *priv); @@ -1197,8 +1197,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat old_mix_dat = mix_dat; - if (cmd != 0) - ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x, ssvdraw=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06, dev->accel.ssv_draw); + ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x, ssvdraw=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06, dev->accel.ssv_draw); /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on @@ -1215,41 +1214,43 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { dev->subsys_stat |= INT_GE_BSY; - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - src_dat = 0; - break; + if (ibm8514_cpu_src(svga) || !cpu_input) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; - default: - break; - } + default: + break; + } - READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - if ((compare_mode == 0) || - ((compare_mode == 0x10) && (dest_dat >= compare)) || - ((compare_mode == 0x18) && (dest_dat < compare)) || - ((compare_mode == 0x20) && (dest_dat != compare)) || - ((compare_mode == 0x28) && (dest_dat == compare)) || - ((compare_mode == 0x30) && (dest_dat <= compare)) || - ((compare_mode == 0x38) && (dest_dat > compare))) { - old_dest_dat = dest_dat; - MIX(mix_dat & mix_mask, dest_dat, src_dat); - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if (dev->accel.ssv_draw) { - if ((dev->accel.cmd & 0x04) && dev->accel.ssv_len) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - } else if (!(dev->accel.cmd & 0x04)) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + if (dev->accel.ssv_draw) { + if ((dev->accel.cmd & 0x04) && dev->accel.ssv_len) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 0x04)) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } } } } @@ -1837,20 +1838,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { dev->subsys_stat |= INT_GE_BSY; - if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { - mix_dat = mix_mask; /* Mix data = forced to foreground register. */ - } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { - /* Mix data = current video memory value. */ - READ((dev->accel.cy * dev->pitch) + dev->accel.cx, mix_dat); - mix_dat = ((mix_dat & rd_mask) == rd_mask); - mix_dat = mix_dat ? mix_mask : 0; - } - - if (ibm8514_cpu_dest(svga)) { - READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); - if (pixcntl == 3) - src_dat = ((src_dat & rd_mask) == rd_mask); - } else + if (ibm8514_cpu_src(svga) || !cpu_input) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1869,21 +1857,18 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat break; } - READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - if ((compare_mode == 0) || - ((compare_mode == 0x10) && (dest_dat >= compare)) || - ((compare_mode == 0x18) && (dest_dat < compare)) || - ((compare_mode == 0x20) && (dest_dat != compare)) || - ((compare_mode == 0x28) && (dest_dat == compare)) || - ((compare_mode == 0x30) && (dest_dat <= compare)) || - ((compare_mode == 0x38) && (dest_dat > compare))) { - old_dest_dat = dest_dat; - MIX(mix_dat & mix_mask, dest_dat, src_dat); - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if ((dev->accel.cmd & 0x04) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - } else if (!(dev->accel.cmd & 0x04)) { + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } } @@ -4038,10 +4023,8 @@ ibm8514_vblank_start(void *priv) static void * ibm8514_init(const device_t *info) { - FILE *fp; - uint8_t *rom_load = NULL; - uint32_t bios_addr = 0; uint16_t bios_rom_eeprom = 0x0000; + uint32_t bios_addr; if (svga_get_pri() == NULL) return NULL; @@ -4067,37 +4050,34 @@ ibm8514_init(const device_t *info) dev->bpp = 0; dev->extensions = device_get_config_int("extensions"); - bios_addr = device_get_config_hex20("bios_addr"); + dev->bios_addr = device_get_config_hex20("bios_addr"); if (dev->type & DEVICE_MCA) - bios_addr = 0xc6800; + dev->bios_addr = 0xc6800; switch (dev->extensions) { case ATI: if (rom_present(BIOS_MACH8_ROM_PATH)) { mach_t * mach = (mach_t *) calloc(1, sizeof(mach_t)); svga->ext8514 = mach; - fp = rom_fopen(BIOS_MACH8_ROM_PATH, "rb"); - if (bios_addr & 0x800) - (void) fseek(fp, 0x000, SEEK_SET); - else - (void) fseek(fp, 0x800, SEEK_SET); + bios_addr = dev->bios_addr; - rom_load = malloc(0x2000); - (void) !fread(rom_load, 0x2000, 1, fp); - (void) fclose(fp); - memset(&dev->bios_rom, 0x00, sizeof(rom_t)); + dev->bios_rom.rom = malloc(0x2000); + memset(dev->bios_rom.rom, 0xff, 0x2000); - dev->bios_rom.rom = rom_load; + (void) rom_load_linear(BIOS_MACH8_ROM_PATH, bios_addr, 0x2000, 0x0000, dev->bios_rom.rom + (bios_addr & 0x0800)); + dev->bios_rom.sz = 0x2000; dev->bios_rom.mask = 0x1fff; - mem_mapping_add(&dev->bios_rom.mapping, bios_addr, 0x2000, - ati8514_rom_readb, ati8514_rom_readw, NULL, + + mem_mapping_add(&dev->bios_rom.mapping, bios_addr, dev->bios_rom.sz, + ati8514_bios_rom_readb, ati8514_bios_rom_readw, ati8514_bios_rom_readl, NULL, NULL, NULL, dev->bios_rom.rom, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM_WS, dev); + ati8514_init(svga, svga->ext8514, svga->dev8514); if (dev->type & DEVICE_MCA) { - dev->accel.scratch0 = (((bios_addr >> 7) - 0x1000) >> 4); - dev->accel.scratch0 |= ((dev->accel.scratch0 + 0x01) << 8); - bios_rom_eeprom = dev->accel.scratch0; + mach->accel.scratch0 = (((dev->bios_addr >> 7) - 0x1000) >> 4); + mach->accel.scratch0 |= ((mach->accel.scratch0 + 0x01) << 8); + bios_rom_eeprom = mach->accel.scratch0; dev->pos_regs[0] = 0x88; dev->pos_regs[1] = 0x80; mach->eeprom.data[1] = bios_rom_eeprom; @@ -4105,8 +4085,9 @@ ibm8514_init(const device_t *info) ati_eeprom_load_mach8(&mach->eeprom, "ati8514_mca.nvr", 1); mem_mapping_disable(&dev->bios_rom.mapping); } else { - dev->accel.scratch0 = ((bios_addr >> 7) - 0x1000) >> 4; - dev->accel.scratch0 |= ((dev->accel.scratch0 + 0x01) << 8); + mach->accel.scratch0 = ((dev->bios_addr >> 7) - 0x1000) >> 4; + mach->accel.scratch0 |= ((mach->accel.scratch0 + 0x01) << 8); + ibm8514_log("Scratch0 init val=%04x, bios=%06x, base=%06x.\n", mach->accel.scratch0, dev->bios_addr, dev->bios_rom.mapping.base); ati_eeprom_load_mach8(&mach->eeprom, "ati8514.nvr", 0); } break; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index fff9bce3e..ab38e26f6 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -333,7 +333,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } } - mach_log("cmd_type = %i, frgd_sel = %i, bkgd_sel = %i, mono_src = %i, dpconfig = %04x, cur_x = %d, cur_y = %d, cl = %d, cr = %d, ct = %d, cb = %d, accel_bpp = %d, pitch = %d, hicolbpp = %d, pattlen = %d.\n", cmd_type, frgd_sel, bkgd_sel, mono_src, mach->accel.dp_config, dev->accel.cur_x, dev->accel.cur_y, clip_l, clip_r, clip_t, clip_b, dev->accel_bpp, dev->pitch, dev->bpp, mach->accel.patt_len); + if (cmd_type == 1 || cmd_type == 3 || cmd_type == 4) { + if (mach->accel.linedraw_opt & 0x04) + mach_log("cmd_type = %i, frgd_sel = %i, bkgd_sel = %i, mono_src = %i, dpconfig = %04x, cur_x = %d, cur_y = %d, cl = %d, cr = %d, ct = %d, cb = %d, accel_bpp = %d, pitch = %d, hicolbpp = %d, pattlen = %d.\n", cmd_type, frgd_sel, bkgd_sel, mono_src, mach->accel.dp_config, dev->accel.cur_x, dev->accel.cur_y, clip_l, clip_r, clip_t, clip_b, dev->accel_bpp, dev->pitch, dev->bpp, mach->accel.patt_len); + } switch (cmd_type) { case 1: /*Extended Raw Linedraw from bres_count register (0x96ee)*/ @@ -437,88 +440,84 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { dev->subsys_stat |= INT_GE_BSY; - switch (mix ? frgd_sel : bkgd_sel) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - if (mach_pixel_read(mach)) + if (mach_pixel_write(mach) || !cpu_input) { + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: src_dat = cpu_dat; - else { + break; + case 3: READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, src_dat); if (mono_src == 3) src_dat = (src_dat & rd_mask) == rd_mask; - } - break; - case 5: - if (dev->bpp) - src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; - else - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; - break; - - default: - break; - } - - if (mach->accel.linedraw_opt & 0x02) { - READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, poly_src); - poly_src = ((poly_src & rd_mask) == rd_mask); - if (poly_src) - mach->accel.poly_fill = !mach->accel.poly_fill; - } - - if (mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { - READ(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); - - switch (compare_mode) { - case 1: - compare = 1; - break; - case 2: - compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; - break; - case 3: - compare = (dest_dat < dest_cmp_clr) ? 0 : 1; - break; - case 4: - compare = (dest_dat != dest_cmp_clr) ? 0 : 1; break; case 5: - compare = (dest_dat == dest_cmp_clr) ? 0 : 1; - break; - case 6: - compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; - break; - case 7: - compare = (dest_dat > dest_cmp_clr) ? 0 : 1; + if (dev->bpp) + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; break; default: break; } - if (!compare) { - if (mach_pixel_write(mach)) { + if (mach->accel.linedraw_opt & 0x02) { + READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, poly_src); + poly_src = ((poly_src & rd_mask) == rd_mask); + if (poly_src) + mach->accel.poly_fill = !mach->accel.poly_fill; + } + + if (mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { + READ(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); + + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = (dest_dat == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = (dest_dat > dest_cmp_clr) ? 0 : 1; + break; + + default: + break; + } + + if (!compare) { old_dest_dat = dest_dat; MIX(mix, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); } - } - if (mach->accel.dp_config & 0x10) { - if (mach->accel.linedraw_opt & 0x04) { - if (((mono_src != 1) && (dev->accel.sx < mach->accel.width)) || ((mono_src == 1) && count)) { + if (mach->accel.dp_config & 0x10) { + if (mach->accel.linedraw_opt & 0x04) { + if (((mono_src != 1) && (dev->accel.sx < mach->accel.width)) || ((mono_src == 1) && count)) { + WRITE(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); + } + } else { WRITE(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); } - } else { - WRITE(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); } } } @@ -647,89 +646,84 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { dev->subsys_stat |= INT_GE_BSY; - switch (mix ? frgd_sel : bkgd_sel) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - if (mach_pixel_read(mach)) - src_dat = cpu_dat; - else { - READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, src_dat); - if (mono_src == 3) { - src_dat = (src_dat & rd_mask) == rd_mask; - } - } - break; - case 5: - if (dev->bpp) - src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; - else - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; - break; - - default: - break; - } - - if (mach->accel.linedraw_opt & 0x02) { - READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, poly_src); - poly_src = ((poly_src & rd_mask) == rd_mask); - if (poly_src) - mach->accel.poly_fill = !mach->accel.poly_fill; - } - - if (mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { - READ(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); - - switch (compare_mode) { + if (mach_pixel_write(mach) || !cpu_input) { + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = bkgd_color; + break; case 1: - compare = 1; + src_dat = frgd_color; break; case 2: - compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; + src_dat = cpu_dat; break; case 3: - compare = (dest_dat < dest_cmp_clr) ? 0 : 1; - break; - case 4: - compare = (dest_dat != dest_cmp_clr) ? 0 : 1; + READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, src_dat); + if (mono_src == 3) + src_dat = (src_dat & rd_mask) == rd_mask; break; case 5: - compare = (dest_dat == dest_cmp_clr) ? 0 : 1; - break; - case 6: - compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; - break; - case 7: - compare = (dest_dat > dest_cmp_clr) ? 0 : 1; + if (dev->bpp) + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; break; default: break; } - if (!compare) { - if (mach_pixel_write(mach)) { + if (mach->accel.linedraw_opt & 0x02) { + READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, poly_src); + poly_src = ((poly_src & rd_mask) == rd_mask); + if (poly_src) + mach->accel.poly_fill = !mach->accel.poly_fill; + } + + if (mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { + READ(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); + + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = (dest_dat == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = (dest_dat > dest_cmp_clr) ? 0 : 1; + break; + + default: + break; + } + + if (!compare) { old_dest_dat = dest_dat; MIX(mix, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); } - } - if (mach->accel.dp_config & 0x10) { - if (mach->accel.linedraw_opt & 0x04) { - if (((mono_src != 1) && (dev->accel.sx < mach->accel.width)) || ((mono_src == 1) && count)) { + if (mach->accel.dp_config & 0x10) { + if (mach->accel.linedraw_opt & 0x04) { + if (((mono_src != 1) && (dev->accel.sx < mach->accel.width)) || ((mono_src == 1) && count)) { + WRITE(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); + } + } else { WRITE(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); } - } else { - WRITE(mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch) + dev->accel.dx, dest_dat); } } } @@ -906,23 +900,27 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (mach->accel.sx_end > mach->accel.sx_start) { mach->accel.src_width = (mach->accel.sx_end - mach->accel.sx_start); mach->accel.src_stepx = 1; - mach_log("BitBLT: Src Positive X: wh(%d,%d), srcwidth = %d, coordinates: %d,%d px, start: %d, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", + if (mach->accel.dp_config == 0x6011) + mach_log("BitBLT: Src Positive X: wh(%d,%d), srcwidth = %d, coordinates: %d,%d px, start: %d, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d, srcpitch = %d, dstpitch = %d, dststepx = %d, dststepy = %d, dx = %d, dy = %d.\n", mach->accel.width, mach->accel.height, mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_start, mach->accel.src_x_end, - mach->accel.src_stepx, mach->accel.dp_config, mach->accel.src_width & 1); + mach->accel.src_stepx, mach->accel.dp_config, mach->accel.src_width & 1, mach->accel.src_pitch, mach->accel.dst_pitch, mach->accel.stepx, mach->accel.stepy, dev->accel.dx, dev->accel.dy); } else if (mach->accel.sx_end < mach->accel.sx_start) { mach->accel.src_width = (mach->accel.sx_start - mach->accel.sx_end); mach->accel.src_stepx = -1; if (dev->accel.cx > 0) dev->accel.cx--; - mach_log("BitBLT: Src Negative X: width = %d, coordinates: %d,%d px, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", - mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_end, mach->accel.src_stepx, mach->accel.dp_config, - mach->accel.src_width & 1); + + if (mach->accel.dp_config == 0x6011) + mach_log("BitBLT: Src Negative X: width = %d, coordinates: %d,%d px, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", + mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_end, mach->accel.src_stepx, mach->accel.dp_config, + mach->accel.src_width & 1); } else { mach->accel.src_stepx = 1; mach->accel.src_width = 0; - mach_log("BitBLT: Src Indeterminate X: width = %d, coordinates: %d,%d px, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", - mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_end, mach->accel.src_stepx, - mach->accel.dp_config, mach->accel.src_width & 1); + if (mach->accel.dp_config == 0x6011) + mach_log("BitBLT: Src Indeterminate X: width = %d, coordinates: %d,%d px, end: %d px, stepx = %d, dpconfig = %04x, oddwidth = %d.\n", + mach->accel.src_width, dev->accel.cx, dev->accel.cy, mach->accel.src_x_end, mach->accel.src_stepx, + mach->accel.dp_config, mach->accel.src_width & 1); } mach->accel.sx = 0; if (mach->accel.patt_data_idx < 0x10) @@ -1075,98 +1073,94 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { dev->subsys_stat |= INT_GE_BSY; - if (mach->accel.dp_config & 0x02) { - READ(dev->accel.src + dev->accel.cx, poly_src); - poly_src = ((poly_src & rd_mask) == rd_mask); - if (poly_src) - mach->accel.poly_fill ^= 1; - } + if (mach_pixel_write(mach) || !cpu_input) { + if (mach->accel.dp_config & 0x02) { + READ(dev->accel.src + dev->accel.cx, poly_src); + poly_src = ((poly_src & rd_mask) == rd_mask); + if (poly_src) + mach->accel.poly_fill ^= 1; + } - if (mach->accel.poly_fill || !(mach->accel.dp_config & 0x02)) { - switch (mix ? frgd_sel : bkgd_sel) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - if (mach_pixel_read(mach)) + if (mach->accel.poly_fill || !(mach->accel.dp_config & 0x02)) { + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: src_dat = cpu_dat; - else { + break; + case 3: READ(dev->accel.src + dev->accel.cx, src_dat); if (mono_src == 3) src_dat = (src_dat & rd_mask) == rd_mask; + break; + case 5: + if (dev->bpp) + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; + break; + + default: + break; + } + + if ((dev->accel_bpp == 24) && (mono_src == 1) && (frgd_sel == 5) && !mach->accel.mono_pattern_enable) { + if (dev->accel.sy & 1) { + READ(dev->accel.dest + dev->accel.dx - mach->accel.dst_pitch, dest_dat); + } else { + READ(dev->accel.dest + dev->accel.dx, dest_dat); } - break; - case 5: - if (dev->bpp) - src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; - else - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; - break; - - default: - break; - } - - if ((dev->accel_bpp == 24) && (mono_src == 1) && (frgd_sel == 5) && !mach->accel.mono_pattern_enable) { - if (dev->accel.sy & 1) { - READ(dev->accel.dest + dev->accel.dx - mach->accel.dst_pitch, dest_dat); } else { READ(dev->accel.dest + dev->accel.dx, dest_dat); } - } else { - READ(dev->accel.dest + dev->accel.dx, dest_dat); - } - switch (compare_mode) { - case 1: - compare = 1; - break; - case 2: - compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; - break; - case 3: - compare = (dest_dat < dest_cmp_clr) ? 0 : 1; - break; - case 4: - compare = (dest_dat != dest_cmp_clr) ? 0 : 1; - break; - case 5: - compare = (dest_dat == dest_cmp_clr) ? 0 : 1; - break; - case 6: - compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; - break; - case 7: - compare = (dest_dat > dest_cmp_clr) ? 0 : 1; - break; + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = (dest_dat == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = (dest_dat > dest_cmp_clr) ? 0 : 1; + break; - default: - break; - } + default: + break; + } - if (!compare) { - if (mach_pixel_write(mach)) { + if (!compare) { old_dest_dat = dest_dat; MIX(mix, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); } - } - if (mach->accel.dp_config & 0x10) { - if ((dev->accel_bpp == 24) && (mono_src == 1) && (frgd_sel == 5) && !mach->accel.mono_pattern_enable) { - if (dev->accel.sy & 1) { - WRITE(dev->accel.dest + dev->accel.dx - mach->accel.dst_pitch, dest_dat); + if (mach->accel.dp_config & 0x10) { + if ((dev->accel_bpp == 24) && (mono_src == 1) && (frgd_sel == 5) && !mach->accel.mono_pattern_enable) { + if (dev->accel.sy & 1) { + WRITE(dev->accel.dest + dev->accel.dx - mach->accel.dst_pitch, dest_dat); + } else { + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } } else { WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } - } else { - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } } } @@ -1186,15 +1180,29 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if ((mono_src == 3) || (frgd_sel == 3) || (bkgd_sel == 3) || (mach->accel.dp_config & 0x02)) { dev->accel.cx += mach->accel.src_stepx; mach->accel.sx++; - if (mach->accel.sx >= mach->accel.src_width) { - mach->accel.sx = 0; - if (mach->accel.src_stepx == -1) - dev->accel.cx += mach->accel.src_width; - else - dev->accel.cx -= mach->accel.src_width; + if (mach->accel.dp_config == 0x6011) { + mach_log("DX=%d, DY=%d, SX=%d, SY=%d, SRCSX=%d, SRCWIDTH=%d, CX=%d, CY=%d, srcydir=%d, srcoffset=%08x.\n", dev->accel.dx, dev->accel.dy, dev->accel.sx, dev->accel.sy, mach->accel.sx - 1, mach->accel.src_width, dev->accel.cx - mach->accel.src_stepx, dev->accel.cy, mach->accel.src_y_dir, mach->accel.src_ge_offset); + if (mach->accel.sx >= mach->accel.src_width) { + mach->accel.sx = 0; + if (mach->accel.src_stepx == -1) + dev->accel.cx += mach->accel.src_width; + else + dev->accel.cx -= mach->accel.src_width; - dev->accel.cy += (mach->accel.src_y_dir ? 1 : -1); - dev->accel.src = mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch); + dev->accel.cy += mach->accel.stepy; + dev->accel.src = mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch); + } + } else { + if (mach->accel.sx >= mach->accel.src_width) { + mach->accel.sx = 0; + if (mach->accel.src_stepx == -1) + dev->accel.cx += mach->accel.src_width; + else + dev->accel.cx -= mach->accel.src_width; + + dev->accel.cy += mach->accel.src_y_dir; + dev->accel.src = mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch); + } } } @@ -1211,7 +1219,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dev->accel.dx += mach->accel.stepx; dev->accel.sx++; if ((dev->accel.sx >= mach->accel.width) || (dev->accel.dx >= 0x600)) { - dev->accel.sx = 0; + dev->accel.sx = 0; if (mach->accel.stepx == -1) dev->accel.dx += mach->accel.width; else @@ -1318,71 +1326,68 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cy <= clip_b)) { dev->subsys_stat |= INT_GE_BSY; mach->accel.clip_overrun = 0; - switch (mix ? frgd_sel : bkgd_sel) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - if (mach_pixel_read(mach)) + if (mach_pixel_write(mach) || !cpu_input) { + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: src_dat = cpu_dat; - else + break; + case 3: src_dat = 0; - break; - case 5: - if (dev->bpp) - src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; - else - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; - break; + break; + case 5: + if (dev->bpp) + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; + break; - default: - break; - } + default: + break; + } - READ(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); + READ(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); - switch (compare_mode) { - case 1: - compare = 1; - break; - case 2: - compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; - break; - case 3: - compare = (dest_dat < dest_cmp_clr) ? 0 : 1; - break; - case 4: - compare = (dest_dat != dest_cmp_clr) ? 0 : 1; - break; - case 5: - compare = (dest_dat == dest_cmp_clr) ? 0 : 1; - break; - case 6: - compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; - break; - case 7: - compare = (dest_dat > dest_cmp_clr) ? 0 : 1; - break; + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = (dest_dat == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = (dest_dat > dest_cmp_clr) ? 0 : 1; + break; - default: - break; - } + default: + break; + } - if (!compare) { - if (mach_pixel_write(mach)) { + if (!compare) { old_dest_dat = dest_dat; MIX(mix, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); } - } - if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { - WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); + if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { + WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); + } } } else mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); @@ -1448,86 +1453,82 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cy <= clip_b)) { dev->subsys_stat |= INT_GE_BSY; mach->accel.clip_overrun = 0; - if (mach->accel.linedraw_opt & 0x02) { - READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, poly_src); - if (poly_src) - mach->accel.poly_fill ^= 1; - } + if (mach_pixel_write(mach) || !cpu_input) { + if (mach->accel.linedraw_opt & 0x02) { + READ(mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch) + dev->accel.cx, poly_src); + if (poly_src) + mach->accel.poly_fill ^= 1; + } - switch (mix ? frgd_sel : bkgd_sel) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - if (mach_pixel_read(mach)) + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: src_dat = cpu_dat; - else { + break; + case 3: src_dat = 0; - } - break; - case 5: - if (dev->bpp) - src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; - else - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; - break; + break; + case 5: + if (dev->bpp) + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; + break; - default: - break; - } + default: + break; + } - READ(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); + READ(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); - switch (compare_mode) { - case 1: - compare = 1; - break; - case 2: - compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; - break; - case 3: - compare = (dest_dat < dest_cmp_clr) ? 0 : 1; - break; - case 4: - compare = (dest_dat != dest_cmp_clr) ? 0 : 1; - break; - case 5: - compare = (dest_dat == dest_cmp_clr) ? 0 : 1; - break; - case 6: - compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; - break; - case 7: - compare = (dest_dat > dest_cmp_clr) ? 0 : 1; - break; + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = (dest_dat == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = (dest_dat > dest_cmp_clr) ? 0 : 1; + break; - default: - break; - } + default: + break; + } - if (!compare) { - if (mach_pixel_write(mach)) { + if (!compare) { old_dest_dat = dest_dat; if (mach->accel.poly_fill || !(mach->accel.linedraw_opt & 0x02)) { MIX(mix, dest_dat, src_dat); } dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); } - } - if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { - if (mach->accel.linedraw_opt & 0x04) { - if (dev->accel.sx < mach->accel.width) { + if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { + if (mach->accel.linedraw_opt & 0x04) { + if (dev->accel.sx < mach->accel.width) { + WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); + } + } else { WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); } - } else { - WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); } } } else @@ -1583,73 +1584,69 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cy <= clip_b)) { dev->subsys_stat |= INT_GE_BSY; mach->accel.clip_overrun = 0; - switch (mix ? frgd_sel : bkgd_sel) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - if (mach_pixel_read(mach)) + if (mach_pixel_write(mach) || !cpu_input) { + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: src_dat = cpu_dat; - else { + break; + case 3: src_dat = 0; - } - break; - case 5: - if (dev->bpp) - src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; - else - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; - break; + break; + case 5: + if (dev->bpp) + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; + break; - default: - break; - } + default: + break; + } - READ(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); + READ(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); - switch (compare_mode) { - case 1: - compare = 1; - break; - case 2: - compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; - break; - case 3: - compare = (dest_dat < dest_cmp_clr) ? 0 : 1; - break; - case 4: - compare = (dest_dat != dest_cmp_clr) ? 0 : 1; - break; - case 5: - compare = (dest_dat == dest_cmp_clr) ? 0 : 1; - break; - case 6: - compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; - break; - case 7: - compare = (dest_dat > dest_cmp_clr) ? 0 : 1; - break; + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = (dest_dat == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = (dest_dat > dest_cmp_clr) ? 0 : 1; + break; - default: - break; - } + default: + break; + } - if (!compare) { - if (mach_pixel_write(mach)) { + if (!compare) { old_dest_dat = dest_dat; MIX(mix, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); } - } - if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { - WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); + if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { + WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); + } } } else mach->accel.clip_overrun = ((mach->accel.clip_overrun + 1) & 0x0f); @@ -1715,78 +1712,74 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cy <= clip_b)) { dev->subsys_stat |= INT_GE_BSY; mach->accel.clip_overrun = 0; - switch (mix ? frgd_sel : bkgd_sel) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - if (mach_pixel_read(mach)) + if (mach_pixel_write(mach) || !cpu_input) { + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: src_dat = cpu_dat; - else { + break; + case 3: src_dat = 0; - } - break; - case 5: - if (dev->bpp) - src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; - else - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; - break; + break; + case 5: + if (dev->bpp) + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; + break; - default: - break; - } + default: + break; + } - READ(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); + READ(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); - switch (compare_mode) { - case 1: - compare = 1; - break; - case 2: - compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; - break; - case 3: - compare = (dest_dat < dest_cmp_clr) ? 0 : 1; - break; - case 4: - compare = (dest_dat != dest_cmp_clr) ? 0 : 1; - break; - case 5: - compare = (dest_dat == dest_cmp_clr) ? 0 : 1; - break; - case 6: - compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; - break; - case 7: - compare = (dest_dat > dest_cmp_clr) ? 0 : 1; - break; + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = (dest_dat == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = (dest_dat > dest_cmp_clr) ? 0 : 1; + break; - default: - break; - } + default: + break; + } - if (!compare) { - if (mach_pixel_write(mach)) { + if (!compare) { old_dest_dat = dest_dat; MIX(mix, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); } - } - if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { - if (mach->accel.linedraw_opt & 0x04) { - if (dev->accel.sx < mach->accel.width) { + if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { + if (mach->accel.linedraw_opt & 0x04) { + if (dev->accel.sx < mach->accel.width) { + WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); + } + } else { WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); } - } else { - WRITE(mach->accel.dst_ge_offset + (dev->accel.cy * mach->accel.dst_pitch) + dev->accel.cx, dest_dat); } } } else @@ -2016,7 +2009,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 cx--; } - cy += (mach->accel.src_y_dir ? 1 : -1); + cy += mach->accel.src_y_dir; dev->accel.src = mach->accel.src_ge_offset + (cy * mach->accel.src_pitch); } @@ -2099,75 +2092,71 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { dev->subsys_stat |= INT_GE_BSY; - switch (mix ? frgd_sel : bkgd_sel) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - if (mach_pixel_read(mach)) + if (mach_pixel_write(mach) || !cpu_input) { + switch (mix ? frgd_sel : bkgd_sel) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: src_dat = cpu_dat; - else { + break; + case 3: READ(dev->accel.src + dev->accel.cx, src_dat); if (mono_src == 3) src_dat = (src_dat & rd_mask) == rd_mask; - } - break; - case 5: - if (dev->bpp) - src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; - else - src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; - break; + break; + case 5: + if (dev->bpp) + src_dat = mach->accel.color_pattern_hicol[mach->accel.color_pattern_idx]; + else + src_dat = mach->accel.color_pattern[mach->accel.color_pattern_idx]; + break; - default: - break; - } + default: + break; + } - READ(dev->accel.dest + dev->accel.dx, dest_dat); + READ(dev->accel.dest + dev->accel.dx, dest_dat); - switch (compare_mode) { - case 1: - compare = 1; - break; - case 2: - compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; - break; - case 3: - compare = (dest_dat < dest_cmp_clr) ? 0 : 1; - break; - case 4: - compare = (dest_dat != dest_cmp_clr) ? 0 : 1; - break; - case 5: - compare = (dest_dat == dest_cmp_clr) ? 0 : 1; - break; - case 6: - compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; - break; - case 7: - compare = (dest_dat > dest_cmp_clr) ? 0 : 1; - break; + switch (compare_mode) { + case 1: + compare = 1; + break; + case 2: + compare = (dest_dat >= dest_cmp_clr) ? 0 : 1; + break; + case 3: + compare = (dest_dat < dest_cmp_clr) ? 0 : 1; + break; + case 4: + compare = (dest_dat != dest_cmp_clr) ? 0 : 1; + break; + case 5: + compare = (dest_dat == dest_cmp_clr) ? 0 : 1; + break; + case 6: + compare = (dest_dat <= dest_cmp_clr) ? 0 : 1; + break; + case 7: + compare = (dest_dat > dest_cmp_clr) ? 0 : 1; + break; - default: - break; - } + default: + break; + } - if (!compare) { - if (mach_pixel_write(mach)) { + if (!compare) { old_dest_dat = dest_dat; MIX(mix, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); } - } - if (mach->accel.dp_config & 0x10) { - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + if (mach->accel.dp_config & 0x10) { + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } } } @@ -2185,7 +2174,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 else dev->accel.cx -= mach->accel.src_width; - dev->accel.cy += (mach->accel.src_y_dir ? 1 : -1); + dev->accel.cy += mach->accel.src_y_dir; dev->accel.src = mach->accel.src_ge_offset + (dev->accel.cy * mach->accel.src_pitch); } @@ -3942,7 +3931,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u } else dev->_8514crt = 1; - if (dev->mode != VGA_MODE) + if ((dev->mode != VGA_MODE) && ATI_MACH32) mach_set_resolution(mach, svga); else svga_recalctimings(svga); @@ -4067,9 +4056,9 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x52ef: mach_log("ATI 8514/A: (0x%04x) ScratchPad0 val=%04x.\n", port, val); if (len == 2) - dev->accel.scratch0 = val; + mach->accel.scratch0 = val; else { - WRITE8(port, dev->accel.scratch0, val); + WRITE8(port, mach->accel.scratch0, val); } break; @@ -4077,9 +4066,9 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0x56ef: mach_log("ATI 8514/A: (0x%04x) ScratchPad1 val=%04x.\n", port, val); if (len == 2) - dev->accel.scratch1 = val; + mach->accel.scratch1 = val; else { - WRITE8(port, dev->accel.scratch1, val); + WRITE8(port, mach->accel.scratch1, val); } break; @@ -4360,7 +4349,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0xc2ee: - mach->accel.src_y_dir = val & 1; + mach->accel.src_y_dir = (val & 1) ? 1 : -1; + mach_log("Source Y Direction=%x.\n", val); break; case 0xc6ee: @@ -5170,16 +5160,16 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) case 0x52ee: case 0x52ef: - READ8(port, dev->accel.scratch0); - mach_log("ScratchPad0=%x.\n", dev->accel.scratch0); - if (dev->accel.scratch0 == 0x1234) + READ8(port, mach->accel.scratch0); + mach_log("ScratchPad0=%x.\n", mach->accel.scratch0); + if (mach->accel.scratch0 == 0x1234) temp = 0x0000; break; case 0x56ee: case 0x56ef: - READ8(port, dev->accel.scratch1); - mach_log("ScratchPad1=%x.\n", dev->accel.scratch1); + READ8(port, mach->accel.scratch1); + mach_log("ScratchPad1=%x.\n", mach->accel.scratch1); break; case 0x5eee: @@ -7326,34 +7316,47 @@ mach_reset(void *priv) } uint8_t -ati8514_rom_readb(uint32_t addr, void *priv) +ati8514_bios_rom_readb(uint32_t addr, void *priv) { const ibm8514_t *dev = (ibm8514_t *) priv; const rom_t *rom = &dev->bios_rom; - uint8_t ret; + uint8_t ret = 0xff; - mach_log("ROM1RB=%05x, ", addr); + mach_log("%04X:%08X: ROM1RB=%05x, ", CS, cpu_state.pc, addr); + addr &= rom->mask; - addr &= 0x1fff; ret = rom->rom[addr]; - - mach_log("ReadBAddr1=%03x, ret=%02x.\n", addr, ret); + mach_log("BIOS: ReadBAddr1=%04x, ret=%02x.\n", addr, ret); return (ret); } uint16_t -ati8514_rom_readw(uint32_t addr, void *priv) +ati8514_bios_rom_readw(uint32_t addr, void *priv) { const ibm8514_t *dev = (ibm8514_t *) priv; const rom_t *rom = &dev->bios_rom; - uint16_t ret; + uint16_t ret = 0xffff; - mach_log("ROM1RW=%05x, ", addr); + mach_log("%04X:%08X: ROM1RW=%05x, ", CS, cpu_state.pc, addr); + addr &= rom->mask; - addr &= 0x1fff; ret = (*(uint16_t *) &(rom->rom[addr])); + mach_log("BIOS: ReadWAddr1=%04x, ret=%04x.\n", addr, ret); + return (ret); +} - mach_log("ReadWAddr1=%03x, ret=%04x.\n", addr, ret); +uint32_t +ati8514_bios_rom_readl(uint32_t addr, void *priv) +{ + const ibm8514_t *dev = (ibm8514_t *) priv; + const rom_t *rom = &dev->bios_rom; + uint32_t ret = 0xffffffff; + + mach_log("%04X:%08X: ROM1RL=%05x, ", CS, cpu_state.pc, addr); + addr &= rom->mask; + + ret = (*(uint32_t *) &(rom->rom[addr])); + mach_log("BIOS: ReadLAddr1=%04x, ret=%08x.\n", addr, ret); return (ret); } diff --git a/src/video/vid_rtg310x.c b/src/video/vid_rtg310x.c index 76b8d8f3f..f43e7f643 100644 --- a/src/video/vid_rtg310x.c +++ b/src/video/vid_rtg310x.c @@ -76,7 +76,7 @@ rtg_in(uint16_t addr, void *priv) case 0x3cf: if (svga->gdcaddr == 0x0c) - return svga->gdcreg[0x0c] | 4; + return svga->gdcreg[0x0c] | 0x04; else if ((svga->gdcaddr > 8) && (svga->gdcaddr != 0x0c)) return svga->gdcreg[svga->gdcaddr]; break; @@ -89,13 +89,13 @@ rtg_in(uint16_t addr, void *priv) return dev->type << 6; if (svga->crtcreg == 0x1e) { ret = svga->crtc[0x1e]; - ret &= ~3; + ret &= ~0x03; if (dev->vram_size == 1024) - ret = 2; + ret = 0x02; else if (dev->vram_size == 512) - ret = 1; + ret = 0x01; else - ret = 0; + ret = 0x00; return ret; } return svga->crtc[svga->crtcreg]; @@ -207,60 +207,60 @@ rtg_out(uint16_t addr, uint8_t val, void *priv) static void rtg_recalctimings(svga_t *svga) { - const rtg_t *dev = (rtg_t *) svga->priv; + const rtg_t *dev = (rtg_t *) svga->priv; + int clk_sel = ((svga->miscout >> 2) & 0x03) | ((svga->gdcreg[0x0c] & 0x20) >> 3); svga->memaddr_latch |= ((svga->crtc[0x19] & 0x10) << 16) | ((svga->crtc[0x19] & 0x40) << 17); - svga->interlace = (svga->crtc[0x19] & 1); + svga->interlace = (svga->crtc[0x19] & 0x01); - /*Clock table not available, currently a guesswork*/ - switch (((svga->miscout >> 2) & 3) | ((svga->gdcreg[0x0c] & 0x20) >> 3)) { - case 0: - case 1: - break; + /*Source: xfree86 3.3.6 source code, rt_driver.c.*/ + switch (clk_sel) { case 2: - svga->clock = (cpuclock * (double) (1ULL << 32)) / 36000000.0; - break; - case 3: - svga->clock = (cpuclock * (double) (1ULL << 32)) / 65100000.0; - break; - case 4: svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; break; + case 3: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 71600000.0; + break; + case 4: + svga->clock = (cpuclock * (double) (1ULL << 32)) / 73000000.0; + break; case 5: - svga->clock = (cpuclock * (double) (1ULL << 32)) / 50000000.0; + svga->clock = (cpuclock * (double) (1ULL << 32)) / 64000000.0; break; case 6: - svga->clock = (cpuclock * (double) (1ULL << 32)) / 80000000.0; + svga->clock = (cpuclock * (double) (1ULL << 32)) / 84000000.0; break; case 7: - svga->clock = (cpuclock * (double) (1ULL << 32)) / 75000000.0; + svga->clock = (cpuclock * (double) (1ULL << 32)) / 79000000.0; break; default: break; } - switch (svga->gdcreg[0x0c] & 3) { - case 1: - svga->clock /= 1.5; - break; - case 2: - svga->clock /= 2; - break; - case 3: - svga->clock /= 4; - break; + if (clk_sel >= 2) { + switch (svga->gdcreg[0x0b] & 0x03) { + case 1: + svga->clock *= 1.5; + break; + case 2: + svga->clock *= 2.0; + break; + case 3: + svga->clock *= 4.0; + break; - default: - break; + default: + break; + } } if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { switch (svga->gdcreg[5] & 0x60) { case 0x00: - if (svga->seqregs[1] & 8) /*Low res (320)*/ + if (svga->seqregs[1] & 0x08) /*Low res (320)*/ svga->render = svga_render_4bpp_lowres; else { if (svga->hdisp == 1280) @@ -270,17 +270,18 @@ rtg_recalctimings(svga_t *svga) } break; case 0x20: /*4 colours*/ - if (svga->seqregs[1] & 8) /*Low res (320)*/ + if (svga->seqregs[1] & 0x08) /*Low res (320)*/ svga->render = svga_render_2bpp_lowres; else svga->render = svga_render_2bpp_highres; break; case 0x40: case 0x60: - if (svga->crtc[0x19] & 2) { - if (svga->hdisp == 1280) + if (svga->crtc[0x19] & 0x02) { + if (svga->hdisp == 1280) { svga->hdisp >>= 1; - else if (dev->type == 2) + svga->dots_per_clock >>= 1; + } else if (dev->type == 2) svga->rowoffset <<= 1; svga->render = svga_render_8bpp_highres; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 2409d1202..0a2866413 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -814,6 +814,7 @@ svga_recalctimings(svga_t *svga) svga->render = svga_render_2bpp_highres; } else { svga->map8 = svga->pallook; + svga_log("Map8.\n"); if (svga->lowres) { /*Low res (320)*/ svga->render = svga_render_8bpp_lowres; svga_log("8 bpp low res.\n");