From a8c75fb0af3c4d1dac3ee49b26dc2d7c9aa0239a Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:34:51 +0900 Subject: [PATCH 01/82] added IBM ESDI Integrated Fixed Disk --- src/disk/hdc.c | 1 + src/disk/hdc_esdi_mca.c | 233 ++++++++++++++++++++++++++++++++++------ 2 files changed, 203 insertions(+), 31 deletions(-) diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 908cbce07..3ec6358d8 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -77,6 +77,7 @@ static const struct { { &xtide_acculogic_device }, { &xtide_device }, { &esdi_ps2_device }, + { &esdi_integrated_device }, { &ide_pci_device }, { &ide_pci_2ch_device }, { &ide_vlb_device }, diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index c906c7ca1..047089a1e 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -150,6 +150,11 @@ typedef struct esdi_t { uint8_t pos_regs[8]; } esdi_t; +enum { + ESDI_IS_ADAPTER, + ESDI_IS_INTEGRATED +}; + #define STATUS_DMA_ENA (1 << 7) #define STATUS_IRQ_PENDING (1 << 6) #define STATUS_CMD_IN_PROGRESS (1 << 5) @@ -635,32 +640,48 @@ esdi_callback(void *priv) break; case CMD_GET_DEV_CONFIG: - ESDI_DRIVE_ONLY(); - - if (!drive->present) { - device_not_present(dev); - return; + if (dev->cmd_dev == ATTN_HOST_ADAPTER) + { + if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) + fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); + /* INT 13, AX=1C0B - ESDI FIXED DISK - GET ADAPTER CONFIGURATION */ + /* The PS/55 will test sector buffer after this request is done. */ + dev->status_len = 6; + dev->status_data[0] = CMD_GET_DEV_CONFIG | STATUS_LEN(6) | STATUS_DEVICE_HOST_ADAPTER; + dev->status_data[1] = 0; + dev->status_data[2] = 0; + /* bit 15-12: chip revision = 0011b, bit 11-8: sector buffer size = n * 256 bytes (n must be < 6) */ + dev->status_data[3] = 0x3200; + dev->status_data[4] = 0; + dev->status_data[5] = 0; } + else + { + ESDI_DRIVE_ONLY(); + if (!drive->present) { + device_not_present(dev); + return; + } - if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) - fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); - - dev->status_len = 6; - dev->status_data[0] = CMD_GET_DEV_CONFIG | STATUS_LEN(6) | STATUS_DEVICE_HOST_ADAPTER; - dev->status_data[1] = 0x10; /*Zero defect*/ - dev->status_data[2] = drive->sectors & 0xffff; - dev->status_data[3] = drive->sectors >> 16; - dev->status_data[4] = drive->tracks; - dev->status_data[5] = drive->hpc | (drive->spt << 16); + if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) + fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); + dev->status_len = 6; + dev->status_data[0] = CMD_GET_DEV_CONFIG | STATUS_LEN(6) | STATUS_DEVICE_HOST_ADAPTER; + dev->status_data[1] = 0x10; /*Zero defect*/ + dev->status_data[2] = drive->sectors & 0xffff; + dev->status_data[3] = drive->sectors >> 16; + dev->status_data[4] = drive->tracks; + dev->status_data[5] = drive->hpc | (drive->spt << 16); + } esdi_mca_log("CMD_GET_DEV_CONFIG %i %04x %04x %04x %04x %04x %04x\n", - drive->sectors, - dev->status_data[0], dev->status_data[1], - dev->status_data[2], dev->status_data[3], - dev->status_data[4], dev->status_data[5]); + drive->sectors, + dev->status_data[0], dev->status_data[1], + dev->status_data[2], dev->status_data[3], + dev->status_data[4], dev->status_data[5]); - dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; - dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; dev->irq_in_progress = 1; set_irq(dev); ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0); @@ -674,7 +695,7 @@ esdi_callback(void *priv) dev->status_len = 5; dev->status_data[0] = CMD_GET_POS_INFO | STATUS_LEN(5) | STATUS_DEVICE_HOST_ADAPTER; - dev->status_data[1] = 0xffdd; /*MCA ID*/ + dev->status_data[1] = dev->pos_regs[1] | (dev->pos_regs[0] << 8); /*MCA ID*/ dev->status_data[2] = dev->pos_regs[3] | (dev->pos_regs[2] << 8); dev->status_data[3] = 0xff; dev->status_data[4] = 0xff; @@ -1171,6 +1192,62 @@ esdi_mca_write(int port, uint8_t val, void *priv) } } +static void +esdi_integrated_mca_write(int port, uint8_t val, void* priv) +{ + esdi_t* dev = (esdi_t*)priv; + + esdi_mca_log("ESDI: mcawr(%04x, %02x) pos[2]=%02x pos[3]=%02x\n", + port, val, dev->pos_regs[2], dev->pos_regs[3]); + + if (port < 0x102) + return; + + /* Save the new value. */ + dev->pos_regs[port & 7] = val; + + io_removehandler(ESDI_IOADDR_PRI, 8, + esdi_read, esdi_readw, NULL, + esdi_write, esdi_writew, NULL, dev); + + switch (dev->pos_regs[2] & 0x3c) { + case 0x14: + dev->dma = 5; + break; + case 0x18: + dev->dma = 6; + break; + case 0x1c: + dev->dma = 7; + break; + case 0x00: + dev->dma = 0; + break; + case 0x04: + dev->dma = 1; + break; + case 0x0c: + dev->dma = 3; + break; + case 0x10: + dev->dma = 4; + break; + + default: + break; + } + + if (dev->pos_regs[2] & 1) { + io_sethandler(ESDI_IOADDR_PRI, 8, + esdi_read, esdi_readw, NULL, + esdi_write, esdi_writew, NULL, dev); + + /* Say hello. */ + esdi_mca_log("ESDI: I/O=3510, IRQ=14, DMA=%d\n", + dev->dma); + } +} + static uint8_t esdi_mca_feedb(void *priv) { @@ -1179,6 +1256,14 @@ esdi_mca_feedb(void *priv) return (dev->pos_regs[2] & 1); } +static void esdi_reset(void* priv) +{ + esdi_t* dev = (esdi_t*)priv; + dev->in_reset = 1; + esdi_mca_set_callback(dev, ESDI_TIME * 50); + dev->status = STATUS_BUSY; +} + static void * esdi_init(UNUSED(const device_t *info)) { @@ -1195,10 +1280,12 @@ esdi_init(UNUSED(const device_t *info)) /* Mark as unconfigured. */ dev->irq_status = 0xff; - rom_init_interleaved(&dev->bios_rom, - BIOS_FILE_H, BIOS_FILE_L, - 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - mem_mapping_disable(&dev->bios_rom.mapping); + if (info->local == ESDI_IS_ADAPTER) { + rom_init_interleaved(&dev->bios_rom, + BIOS_FILE_H, BIOS_FILE_L, + 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&dev->bios_rom.mapping); + } dev->drives[0].present = dev->drives[1].present = 0; @@ -1231,12 +1318,28 @@ esdi_init(UNUSED(const device_t *info)) break; } - /* Set the MCA ID for this controller, 0xFFDD. */ - dev->pos_regs[0] = 0xff; - dev->pos_regs[1] = 0xdd; + /* Set the MCA ID for this controller. */ + if (info->local == ESDI_IS_ADAPTER) { + dev->pos_regs[0] = 0xff; + dev->pos_regs[1] = 0xdd; + } + else if (info->local == ESDI_IS_INTEGRATED) + { + dev->pos_regs[0] = 0x9f; + dev->pos_regs[1] = 0xdf; + } /* Enable the device. */ - mca_add(esdi_mca_read, esdi_mca_write, esdi_mca_feedb, NULL, dev); + if (info->local == ESDI_IS_INTEGRATED) { + /* The slot number of this controller is fixed by the planar. IBM PS/55 5551-T assigns it #5. */ + int slotno = device_get_config_int("in_esdi_slot"); + if (slotno) + mca_add_to_slot(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, NULL, dev, slotno - 1); + else + mca_add(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, NULL, dev); + } + else + mca_add(esdi_mca_read, esdi_mca_write, esdi_mca_feedb, NULL, dev); /* Mark for a reset. */ dev->in_reset = 1; @@ -1276,7 +1379,7 @@ const device_t esdi_ps2_device = { .name = "IBM PS/2 ESDI Fixed Disk Adapter (MCA)", .internal_name = "esdi_mca", .flags = DEVICE_MCA, - .local = 0, + .local = ESDI_IS_ADAPTER, .init = esdi_init, .close = esdi_close, .reset = NULL, @@ -1285,3 +1388,71 @@ const device_t esdi_ps2_device = { .force_redraw = NULL, .config = NULL }; + +static device_config_t +esdi_integrated_config[] = +{ + { + .name = "in_esdi_slot", + .description = "Slot #", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "Auto", + .value = 0 + }, + { + .description = "1", + .value = 1 + }, + { + .description = "2", + .value = 2 + }, + { + .description = "3", + .value = 3 + }, + { + .description = "4", + .value = 4 + }, + { + .description = "5", + .value = 5 + }, + { + .description = "6", + .value = 6 + }, + { + .description = "7", + .value = 7 + }, + { + .description = "8", + .value = 8 + } + }, + .default_int = 0 + }, + { + .type = -1 + } +}; + +const device_t +esdi_integrated_device = { + .name = "IBM Integrated Fixed Disk Controller (MCA)", + .internal_name = "esdi_integrated_mca", + .flags = DEVICE_MCA, + .local = ESDI_IS_INTEGRATED, + .init = esdi_init, + .close = esdi_close, + .reset = esdi_reset, + {.available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = esdi_integrated_config +}; From bb9b4dc64fe079a9edfb0e0e7670303a5c85d50a Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:38:48 +0900 Subject: [PATCH 02/82] Added IBM-J 5576 keyboard and scancode set 8Ah --- src/device/keyboard.c | 116 ++++++++ src/device/keyboard_at.c | 555 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 668 insertions(+), 3 deletions(-) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index ea81e7525..4b8bc7365 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -18,10 +18,13 @@ * Copyright 2015-2019 Miran Grca. * Copyright 2017-2019 Fred N. van Kempen. */ +#include #include #include #include +#include #include +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/machine.h> #include <86box/keyboard.h> @@ -49,6 +52,24 @@ uint16_t key_uncapture_1 = 0x04f; /* Numpad End */ uint16_t key_uncapture_2 = 0x14f; /* End */ #endif +#ifdef ENABLE_KBC_AT_LOG +int kbc_at_do_log = ENABLE_KBC_AT_LOG; + +static void +kbc_at_log(const char* fmt, ...) +{ + va_list ap; + + if (kbc_at_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define kbc_at_log(fmt, ...) +#endif + void (*keyboard_send)(uint16_t val); static int recv_key[512] = { 0 }; /* keyboard input buffer */ @@ -64,6 +85,64 @@ static uint8_t num_lock = 0; static uint8_t scroll_lock = 0; static uint8_t shift = 0; +static int key5576mode = 0; + +typedef struct { + const uint16_t sc; + const uint8_t mk[4]; + const uint8_t brk[4]; +} scconvtbl; + +static scconvtbl scconv55_82[18 + 1] = +{ + // clang-format off + {.sc = 0x02 , .mk = { 0x5f, 0 }, .brk = { 0xf0, 0x5f, 0 } }, /* '1' -> 'Clear/ /SysRq' */ + {.sc = 0x03 , .mk = { 0x48, 0 }, .brk = { 0xf0, 0x48, 0 } }, /* '2' -> '終了 (Exit)' */ + {.sc = 0x04 , .mk = { 0x38, 0 }, .brk = { 0xf0, 0x38, 0 } }, /* '3' -> 'メッセージ (Message)/ /応答 (Respond)' */ + {.sc = 0x05 , .mk = { 0x30, 0 }, .brk = { 0xf0, 0x30, 0 } }, /* '4' -> 'サイズ変換 (Change Size)/ /横倍角 (2x Width)' */ + {.sc = 0x06 , .mk = { 0x20, 0 }, .brk = { 0xf0, 0x20, 0 } }, /* '5' -> '単語登録 (Register Word)/ /再交換 (Re-change)' */ + {.sc = 0x07 , .mk = { 0x28, 0 }, .brk = { 0xf0, 0x28, 0 } }, /* '6' -> '漢字 (Kanji)/ /番号 (Number)' */ + {.sc = 0x08 , .mk = { 0x60, 0 }, .brk = { 0xf0, 0x60, 0 } }, /* '7' -> '取消 (Cancel)' */ + {.sc = 0x09 , .mk = { 0x40, 0 }, .brk = { 0xf0, 0x40, 0 } }, /* '8' -> 'コピー (Copy)/ /移動 (Move)' */ + {.sc = 0x3d , .mk = { 0x1f, 0 }, .brk = { 0xf0, 0x1f, 0 } }, /* 'F3' -> 'Cr Bnk/領域呼出 (Call Range)/All Cr/登録 (Register)' */ + {.sc = 0x3e , .mk = { 0x27, 0 }, .brk = { 0xf0, 0x27, 0 } }, /* 'F4' -> '割込み (Interrupt)' */ + {.sc = 0x3f , .mk = { 0x2f, 0 }, .brk = { 0xf0, 0x2f, 0 } }, /* 'F5' -> 'UF1' */ + {.sc = 0x40 , .mk = { 0x5e, 0 }, .brk = { 0xf0, 0x5e, 0 } }, /* 'F6' -> 'UF2' */ + {.sc = 0x41 , .mk = { 0x08, 0 }, .brk = { 0xf0, 0x08, 0 } }, /* 'F7' -> 'UF3' */ + {.sc = 0x42 , .mk = { 0x10, 0 }, .brk = { 0xf0, 0x10, 0 } }, /* 'F8' -> 'UF4' */ + {.sc = 0x43 , .mk = { 0x50, 0 }, .brk = { 0xf0, 0x50, 0 } }, /* 'F9' -> 'EOF/Erase/ErInp' */ + {.sc = 0x44 , .mk = { 0x18, 0 }, .brk = { 0xf0, 0x18, 0 } }, /* 'F10' -> 'Attn/ /CrSel' */ + {.sc = 0x57 , .mk = { 0x17, 0 }, .brk = { 0xf0, 0x17, 0 } }, /* 'F11' -> 'PA1/ /DvCncl' */ + {.sc = 0x58 , .mk = { 0x37, 0 }, .brk = { 0xf0, 0x37, 0 } }, /* 'F12' -> 'PA2/ /PA3' */ + {.sc = 0 , .mk = { 0 }, .brk = { 0 } } /* end */ + // clang-format on +}; + +static scconvtbl scconv55_8a[18 + 1] = +{ + // clang-format off + {.sc = 0x02 , .mk = { 0x48 }, .brk = { 0 } }, /* '1' -> 'Clear/ /SysRq' */ + {.sc = 0x03 , .mk = { 0x49 }, .brk = { 0 } }, /* '2' -> '終了 (Exit)' */ + {.sc = 0x04 , .mk = { 0x46 }, .brk = { 0 } }, /* '3' -> 'メッセージ (Message)/ /応答 (Respond)' */ + {.sc = 0x05 , .mk = { 0x44 }, .brk = { 0 } }, /* '4' -> 'サイズ変換 (Change Size)/ /横倍角 (2x Width)' */ + {.sc = 0x06 , .mk = { 0x42 }, .brk = { 0 } }, /* '5' -> '単語登録 (Register Word)/ /再交換 (Re-change)' */ + {.sc = 0x07 , .mk = { 0x43 }, .brk = { 0 } }, /* '6' -> '漢字 (Kanji)/ /番号 (Number)' */ + {.sc = 0x08 , .mk = { 0x40 }, .brk = { 0 } }, /* '7' -> '取消 (Cancel)' */ + {.sc = 0x09 , .mk = { 0x51 }, .brk = { 0 } }, /* '8' -> 'コピー (Copy)/ /移動 (Move)' */ + {.sc = 0x3d , .mk = { 0x76 }, .brk = { 0 } }, /* 'F3' -> 'Cr Bnk/領域呼出 (Call Range)/All Cr/登録 (Register)' */ + {.sc = 0x3e , .mk = { 0x77 }, .brk = { 0 } }, /* 'F4' -> '割込み (Interrupt)' */ + {.sc = 0x3f , .mk = { 0x78 }, .brk = { 0 } }, /* 'F5' -> 'UF1' */ + {.sc = 0x40 , .mk = { 0x79 }, .brk = { 0 } }, /* 'F6' -> 'UF2' */ + {.sc = 0x41 , .mk = { 0x7a }, .brk = { 0 } }, /* 'F7' -> 'UF3' */ + {.sc = 0x42 , .mk = { 0x7b }, .brk = { 0 } }, /* 'F8' -> 'UF4' */ + {.sc = 0x43 , .mk = { 0x7c }, .brk = { 0 } }, /* 'F9' -> 'EOF/Erase/ErInp' */ + {.sc = 0x44 , .mk = { 0x7d }, .brk = { 0 } }, /* 'F10' -> 'Attn/ /CrSel' */ + {.sc = 0x57 , .mk = { 0x7e }, .brk = { 0 } }, /* 'F11' -> 'PA1/ /DvCncl' */ + {.sc = 0x58 , .mk = { 0x7f }, .brk = { 0 } }, /* 'F12' -> 'PA2/ /PA3' */ + {.sc = 0 , .mk = { 0 }, .brk = { 0 } } /* end */ + // clang-format on +}; + void keyboard_init(void) { @@ -119,6 +198,36 @@ key_process(uint16_t scan, int down) oldkey[scan] = down; + pclog("keyboard : %04X,%d in process\n", scan, down); + + c = 0; + /* According to Japanese DOS K3.3 manual (N:SC18-2194-1), + IBM 5576-002, -003 keyboards have the one-time key conversion mode + that emulates 18 out of 131 keys on IBM 5576-001 keyboard. + It is triggered by pressing L-Shift (⇧) + L-Ctrl + R-Alt (前面キー) + when the scancode set is 82h or 8ah. + */ + if (key5576mode) { + int i = 0; + if (!down) { + /* Do and exit the 5576-001 emulation when a key is pressed other than trigger keys. */ + if (scan != 0x1d && scan != 0x2a && scan != 0x138) + { + key5576mode = 0; + pclog("keyboard : 5576-001 key emulation disabled.\n"); + } + } + while (scconv55_8a[i].sc != 0) + { + if (scconv55_8a[i].sc == scan) { + while (scconv55_8a[i].mk[c] != 0) + keyboard_send(scconv55_8a[i].mk[c++]); + return; + } + i++; + } + } + if (down && (codes[scan].mk[0] == 0)) return; @@ -145,6 +254,13 @@ key_process(uint16_t scan, int down) if (fake_shift_needed(scan)) keyboard_send(0x101); } + + /* Enter the 5576-001 emulation mode. */ + if (keyboard_mode == 0x8a && down && ((keyboard_get_shift() & 0x43) == 0x43)) + { + key5576mode = 1; + pclog("keyboard : 5576-001 key emulation enabled.\n"); + } } /* Handle a keystroke event from the UI layer. */ diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index bcb4d646b..2900ec17a 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -53,10 +53,10 @@ const uint8_t id_bytes[16][4] = { { 0x00, 0x00, 0x00, 0x00 }, /* AT 84-key */ { 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, /* FLAG_PS2 = 0x08 */ { 0xab, 0x83, 0x00, 0x00 }, /* PS/2 101-key */ { 0xab, 0x83, 0x00, 0x00 }, /* PS/2 102-key */ - { 0xab, 0x90, 0x00, 0x00 }, /* PS/2 106-key JIS */ + { 0xab, 0x90, 0x00, 0x00 }, /* PS/55 106-key JIS (IBM-J 5576-002) */ /* Japanese keyboard ID - TODO: Find the actual Korean one. */ { 0xab, 0x90, 0x00, 0x00 }, /* PS/2 Korean */ { 0x00, 0x00, 0x00, 0x00 }, @@ -1630,6 +1630,548 @@ static const scancode scancode_set3[512] = { // clang-format on }; +/* IBM Japan 5576-001, 002 and 003 keyboards have three extra scancode sets; 81h, 82h, 8ah. + Scancode set 81h and 82h are not implemented yet. + To implement them, we need take the following into consideration. + * Add a UI to switch the type of keyboards and keyboard IDs. + * Add modified scancode set 1 and 2 (in these modes, language input keys are used as an alternative key). + * Japanese keyboards traditionally use a typewriter layout. Its key mapping doesn't match with foreign keyboards. + + 5576 keyboards kept 101-key compatible scancode sets because PS/55 had to support western (PS/2) versions of operating systems. + The default scancode set is 2. + In Japanese DOS, the keyboard driver confirms its keyboard ID, and sends a command to switch the scancode set to 8Ah. + + The OADG standard and modern Japanese keyboards use the same keyboard ID and scancode set number as PS/2 keyboards use. + Three extra scancode sets are no longer available. Instead, language input keys are available in scancode set 1 and 2. + However, it has a different key mapping. + Users have to choose the correct keyboard layout on setup, and the driver needs to remap keys. + + [Japanese DOS and keyboard scancode set] + | | K3.3 | J4.0 | J5.0 | J4.0/V | J5.0/V | OS/2 J1.3 | PC DOS 5 | + |---------------------------|:----:|:----:|:----:|:------:|:------:|:---------:|:--------:| + | IBM 101-key | n/a | n/a | n/a | n/a | 2 | n/a | 2 | + | IBM-J 5576-00x (obsolete) | 8A | 8A | 8A | 82 | 82 | 82 | 2 | + | OADG (modern JA standard) | n/a | n/a | n/a | 2 | 2 | 2 | 2 | */ + +/* Scancode set 8Ah : 5556 keyboard compatible scancode set used by J-DOS */ +static scancode scancode_set8a[512] = +{ + // clang-format off + {.mk = { 0 }, .brk = { 0 } }, /* 000 */ + {.mk = { 0x3d, 0 }, .brk = { 0 } }, /* 001 */ + {.mk = { 0x24, 0 }, .brk = { 0 } }, /* 002 */ + {.mk = { 0x25, 0 }, .brk = { 0 } }, /* 003 */ + {.mk = { 0x26, 0 }, .brk = { 0 } }, /* 004 */ + {.mk = { 0x27, 0 }, .brk = { 0 } }, /* 005 */ + {.mk = { 0x28, 0 }, .brk = { 0 } }, /* 006 */ + {.mk = { 0x29, 0 }, .brk = { 0 } }, /* 007 */ + {.mk = { 0x2a, 0 }, .brk = { 0 } }, /* 008 */ + {.mk = { 0x2b, 0 }, .brk = { 0 } }, /* 009 */ + {.mk = { 0x2c, 0 }, .brk = { 0 } }, /* 00a */ + {.mk = { 0x2d, 0 }, .brk = { 0 } }, /* 00b */ + {.mk = { 0x2e, 0 }, .brk = { 0 } }, /* 00c */ + {.mk = { 0x2f, 0 }, .brk = { 0 } }, /* 00d */ + {.mk = { 0x3e, 0 }, .brk = { 0 } }, /* 00e */ + {.mk = { 0x3c, 0 }, .brk = { 0 } }, /* 00f */ + {.mk = { 0x18, 0 }, .brk = { 0 } }, /* 010 */ + {.mk = { 0x19, 0 }, .brk = { 0 } }, /* 011 */ + {.mk = { 0x1a, 0 }, .brk = { 0 } }, /* 012 */ + {.mk = { 0x1b, 0 }, .brk = { 0 } }, /* 013 */ + {.mk = { 0x1c, 0 }, .brk = { 0 } }, /* 014 */ + {.mk = { 0x1d, 0 }, .brk = { 0 } }, /* 015 */ + {.mk = { 0x1e, 0 }, .brk = { 0 } }, /* 016 */ + {.mk = { 0x1f, 0 }, .brk = { 0 } }, /* 017 */ + {.mk = { 0x20, 0 }, .brk = { 0 } }, /* 018 */ + {.mk = { 0x21, 0 }, .brk = { 0 } }, /* 019 */ + {.mk = { 0x22, 0 }, .brk = { 0 } }, /* 01a */ + {.mk = { 0x23, 0 }, .brk = { 0 } }, /* 01b */ + {.mk = { 0x3b, 0 }, .brk = { 0 } }, /* 01c */ + {.mk = { 0x41, 0 }, .brk = { 0xc1, 0 } }, /* 01d LCTRL */ + {.mk = { 0x0c, 0 }, .brk = { 0 } }, /* 01e */ + {.mk = { 0x0d, 0 }, .brk = { 0 } }, /* 01f */ + {.mk = { 0x0e, 0 }, .brk = { 0 } }, /* 020 */ + {.mk = { 0x0f, 0 }, .brk = { 0 } }, /* 021 */ + {.mk = { 0x10, 0 }, .brk = { 0 } }, /* 022 */ + {.mk = { 0x11, 0 }, .brk = { 0 } }, /* 023 */ + {.mk = { 0x12, 0 }, .brk = { 0 } }, /* 024 */ + {.mk = { 0x13, 0 }, .brk = { 0 } }, /* 025 */ + {.mk = { 0x14, 0 }, .brk = { 0 } }, /* 026 */ + {.mk = { 0x15, 0 }, .brk = { 0 } }, /* 027 */ + {.mk = { 0x16, 0 }, .brk = { 0 } }, /* 028* */ + {.mk = { 0x45, 0 }, .brk = { 0 } }, /* 029 Hankaku, Zenkaku */ + {.mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 02a LSHIFT */ + {.mk = { 0x17, 0 }, .brk = { 0 } }, /* 02b Mu */ + {.mk = { 0x01, 0 }, .brk = { 0 } }, /* 02c */ + {.mk = { 0x02, 0 }, .brk = { 0 } }, /* 02d */ + {.mk = { 0x03, 0 }, .brk = { 0 } }, /* 02e */ + {.mk = { 0x04, 0 }, .brk = { 0 } }, /* 02f */ + {.mk = { 0x05, 0 }, .brk = { 0 } }, /* 030 */ + {.mk = { 0x06, 0 }, .brk = { 0 } }, /* 031 */ + {.mk = { 0x07, 0 }, .brk = { 0 } }, /* 032 */ + {.mk = { 0x08, 0 }, .brk = { 0 } }, /* 033 */ + {.mk = { 0x09, 0 }, .brk = { 0 } }, /* 034 */ + {.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 LALT = Kanji */ + {.mk = { 0x34, 0 }, .brk = { 0 } }, /* 039 */ + {.mk = { 0x32, 0 }, .brk = { 0xb2, 0 } }, /* 03a CAPSLOCK */ + {.mk = { 0x68, 0 }, .brk = { 0 } }, /* 03b F1 */ + {.mk = { 0x69, 0 }, .brk = { 0 } }, /* 03c */ + {.mk = { 0x6a, 0 }, .brk = { 0 } }, /* 03d */ + {.mk = { 0x6b, 0 }, .brk = { 0 } }, /* 03e */ + {.mk = { 0x6c, 0 }, .brk = { 0 } }, /* 03f */ + {.mk = { 0x6d, 0 }, .brk = { 0 } }, /* 040 */ + {.mk = { 0x6e, 0 }, .brk = { 0 } }, /* 041 */ + {.mk = { 0x6f, 0 }, .brk = { 0 } }, /* 042 */ + {.mk = { 0x70, 0 }, .brk = { 0 } }, /* 043 */ + {.mk = { 0x71, 0 }, .brk = { 0 } }, /* 044 F10 */ + {.mk = { 0 }, .brk = { 0 } }, /* 045 NUMLOCKCLEAR -> Shift + SCRLOCK :TODO */ + {.mk = { 0x75, 0 }, .brk = { 0 } }, /* 046 SCROLLLOCK */ + {.mk = { 0x5d, 0 }, .brk = { 0 } }, /* 047 KP7 */ + {.mk = { 0x5e, 0 }, .brk = { 0 } }, /* 048 */ + {.mk = { 0x5f, 0 }, .brk = { 0 } }, /* 049 */ + {.mk = { 0x67, 0 }, .brk = { 0 } }, /* 04a KP_MINUS */ + {.mk = { 0x5a, 0 }, .brk = { 0 } }, /* 04b */ + {.mk = { 0x5b, 0 }, .brk = { 0 } }, /* 04c */ + {.mk = { 0x5c, 0 }, .brk = { 0 } }, /* 04d */ + {.mk = { 0x63, 0 }, .brk = { 0 } }, /* 04e */ + {.mk = { 0x57, 0 }, .brk = { 0 } }, /* 04f */ + {.mk = { 0x58, 0 }, .brk = { 0 } }, /* 050 */ + {.mk = { 0x59, 0 }, .brk = { 0 } }, /* 051 */ + {.mk = { 0x55, 0 }, .brk = { 0 } }, /* 052 KP0 */ + {.mk = { 0x56, 0 }, .brk = { 0 } }, /* 053 KP_PERIOD */ + {.mk = { 0 }, .brk = { 0 } }, /* 054 */ + {.mk = { 0 }, .brk = { 0 } }, /* 055 */ + {.mk = { 0 }, .brk = { 0 } }, /* 056 */ + {.mk = { 0x72, 0 }, .brk = { 0 } }, /* 057 F11 */ + {.mk = { 0x73, 0 }, .brk = { 0 } }, /* 058 F12 */ + {.mk = { 0 }, .brk = { 0 } }, /* 059 */ + {.mk = { 0 }, .brk = { 0 } }, /* 05a */ + {.mk = { 0 }, .brk = { 0 } }, /* 05b */ + {.mk = { 0 }, .brk = { 0 } }, /* 05c */ + {.mk = { 0 }, .brk = { 0 } }, /* 05d */ + {.mk = { 0 }, .brk = { 0 } }, /* 05e */ + {.mk = { 0 }, .brk = { 0 } }, /* 05f */ + {.mk = { 0 }, .brk = { 0 } }, /* 060 */ + {.mk = { 0 }, .brk = { 0 } }, /* 061 */ + {.mk = { 0 }, .brk = { 0 } }, /* 062 */ + {.mk = { 0 }, .brk = { 0 } }, /* 063 */ + {.mk = { 0 }, .brk = { 0 } }, /* 064 */ + {.mk = { 0 }, .brk = { 0 } }, /* 065 */ + {.mk = { 0 }, .brk = { 0 } }, /* 066 */ + {.mk = { 0 }, .brk = { 0 } }, /* 067 */ + {.mk = { 0 }, .brk = { 0 } }, /* 068 */ + {.mk = { 0 }, .brk = { 0 } }, /* 069 */ + {.mk = { 0 }, .brk = { 0 } }, /* 06a */ + {.mk = { 0 }, .brk = { 0 } }, /* 06b */ + {.mk = { 0 }, .brk = { 0 } }, /* 06c */ + {.mk = { 0 }, .brk = { 0 } }, /* 06d */ + {.mk = { 0 }, .brk = { 0 } }, /* 06e */ + {.mk = { 0 }, .brk = { 0 } }, /* 06f */ + {.mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 070 Kana */ + {.mk = { 0 }, .brk = { 0 } }, /* 071 */ + {.mk = { 0 }, .brk = { 0 } }, /* 072 */ + {.mk = { 0x0b, 0 }, .brk = { 0 } }, /* 073 Ro, Underline */ + {.mk = { 0 }, .brk = { 0 } }, /* 074 */ + {.mk = { 0 }, .brk = { 0 } }, /* 075 */ + {.mk = { 0 }, .brk = { 0 } }, /* 076 */ + {.mk = { 0 }, .brk = { 0 } }, /* 077 */ + {.mk = { 0 }, .brk = { 0 } }, /* 078 */ + {.mk = { 0x35, 0 }, .brk = { 0 } }, /* 079 Henkan */ + {.mk = { 0 }, .brk = { 0 } }, /* 07a */ + {.mk = { 0x33, 0 }, .brk = { 0 } }, /* 07b Muhenkan */ + {.mk = { 0 }, .brk = { 0 } }, /* 07c */ + {.mk = { 0x30, 0 }, .brk = { 0 } }, /* 07d Yen, Vertical line */ + {.mk = { 0 }, .brk = { 0 } }, /* 07e */ + {.mk = { 0 }, .brk = { 0 } }, /* 07f */ + {.mk = { 0 }, .brk = { 0 } }, /* 080 */ + {.mk = { 0 }, .brk = { 0 } }, /* 081 */ + {.mk = { 0 }, .brk = { 0 } }, /* 082 */ + {.mk = { 0 }, .brk = { 0 } }, /* 083 */ + {.mk = { 0 }, .brk = { 0 } }, /* 084 */ + {.mk = { 0 }, .brk = { 0 } }, /* 085 */ + {.mk = { 0 }, .brk = { 0 } }, /* 086 */ + {.mk = { 0 }, .brk = { 0 } }, /* 087 */ + {.mk = { 0 }, .brk = { 0 } }, /* 088 */ + {.mk = { 0 }, .brk = { 0 } }, /* 089 */ + {.mk = { 0 }, .brk = { 0 } }, /* 08a */ + {.mk = { 0 }, .brk = { 0 } }, /* 08b */ + {.mk = { 0 }, .brk = { 0 } }, /* 08c */ + {.mk = { 0 }, .brk = { 0 } }, /* 08d */ + {.mk = { 0 }, .brk = { 0 } }, /* 08e */ + {.mk = { 0 }, .brk = { 0 } }, /* 08f */ + {.mk = { 0 }, .brk = { 0 } }, /* 090 */ + {.mk = { 0 }, .brk = { 0 } }, /* 091 */ + {.mk = { 0 }, .brk = { 0 } }, /* 092 */ + {.mk = { 0 }, .brk = { 0 } }, /* 093 */ + {.mk = { 0 }, .brk = { 0 } }, /* 094 */ + {.mk = { 0 }, .brk = { 0 } }, /* 095 */ + {.mk = { 0 }, .brk = { 0 } }, /* 096 */ + {.mk = { 0 }, .brk = { 0 } }, /* 097 */ + {.mk = { 0 }, .brk = { 0 } }, /* 098 */ + {.mk = { 0 }, .brk = { 0 } }, /* 099 */ + {.mk = { 0 }, .brk = { 0 } }, /* 09a */ + {.mk = { 0 }, .brk = { 0 } }, /* 09b */ + {.mk = { 0 }, .brk = { 0 } }, /* 09c */ + {.mk = { 0 }, .brk = { 0 } }, /* 09d */ + {.mk = { 0 }, .brk = { 0 } }, /* 09e */ + {.mk = { 0 }, .brk = { 0 } }, /* 09f */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0a9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0aa */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ab */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ac */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ad */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ae */ + {.mk = { 0 }, .brk = { 0 } }, /* 0af */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0b9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ba */ + {.mk = { 0 }, .brk = { 0 } }, /* 0bb */ + {.mk = { 0 }, .brk = { 0 } }, /* 0bc */ + {.mk = { 0 }, .brk = { 0 } }, /* 0bd */ + {.mk = { 0 }, .brk = { 0 } }, /* 0be */ + {.mk = { 0 }, .brk = { 0 } }, /* 0bf */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0c9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ca */ + {.mk = { 0 }, .brk = { 0 } }, /* 0cb */ + {.mk = { 0 }, .brk = { 0 } }, /* 0cc */ + {.mk = { 0 }, .brk = { 0 } }, /* 0cd */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ce */ + {.mk = { 0 }, .brk = { 0 } }, /* 0cf */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0d9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0da */ + {.mk = { 0 }, .brk = { 0 } }, /* 0db */ + {.mk = { 0 }, .brk = { 0 } }, /* 0dc */ + {.mk = { 0 }, .brk = { 0 } }, /* 0dd */ + {.mk = { 0 }, .brk = { 0 } }, /* 0de */ + {.mk = { 0 }, .brk = { 0 } }, /* 0df */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0e9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ea */ + {.mk = { 0 }, .brk = { 0 } }, /* 0eb */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ec */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ed */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ee */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ef */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0f9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 0fa */ + {.mk = { 0 }, .brk = { 0 } }, /* 0fb */ + {.mk = { 0 }, .brk = { 0 } }, /* 0fc */ + {.mk = { 0 }, .brk = { 0 } }, /* 0fd */ + {.mk = { 0 }, .brk = { 0 } }, /* 0fe */ + {.mk = { 0 }, .brk = { 0 } }, /* 0ff */ + {.mk = { 0x47, 0 }, .brk = { 0 } }, /* 100 Pause */ + {.mk = { 0 }, .brk = { 0 } }, /* 101 */ + {.mk = { 0 }, .brk = { 0 } }, /* 102 */ + {.mk = { 0 }, .brk = { 0 } }, /* 103 */ + {.mk = { 0 }, .brk = { 0 } }, /* 104 */ + {.mk = { 0 }, .brk = { 0 } }, /* 105 */ + {.mk = { 0 }, .brk = { 0 } }, /* 106 */ + {.mk = { 0 }, .brk = { 0 } }, /* 107 */ + {.mk = { 0 }, .brk = { 0 } }, /* 108 */ + {.mk = { 0 }, .brk = { 0 } }, /* 109 */ + {.mk = { 0 }, .brk = { 0 } }, /* 10a */ + {.mk = { 0 }, .brk = { 0 } }, /* 10b */ + {.mk = { 0 }, .brk = { 0 } }, /* 10c */ + {.mk = { 0 }, .brk = { 0 } }, /* 10d */ + {.mk = { 0 }, .brk = { 0 } }, /* 10e */ + {.mk = { 0 }, .brk = { 0 } }, /* 10f */ + {.mk = { 0 }, .brk = { 0 } }, /* 110 */ + {.mk = { 0 }, .brk = { 0 } }, /* 112 */ + {.mk = { 0 }, .brk = { 0 } }, /* 113 */ + {.mk = { 0 }, .brk = { 0 } }, /* 113 */ + {.mk = { 0 }, .brk = { 0 } }, /* 114 */ + {.mk = { 0 }, .brk = { 0 } }, /* 115 */ + {.mk = { 0 }, .brk = { 0 } }, /* 116 */ + {.mk = { 0 }, .brk = { 0 } }, /* 117 */ + {.mk = { 0 }, .brk = { 0 } }, /* 118 */ + {.mk = { 0 }, .brk = { 0 } }, /* 119 */ + {.mk = { 0 }, .brk = { 0 } }, /* 11a */ + {.mk = { 0 }, .brk = { 0 } }, /* 11b */ + {.mk = { 0x60, 0 }, .brk = { 0 } }, /* 11c KP_Enter */ + {.mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 11d R-Ctrl */ + {.mk = { 0 }, .brk = { 0 } }, /* 11e */ + {.mk = { 0 }, .brk = { 0 } }, /* 11f */ + {.mk = { 0 }, .brk = { 0 } }, /* 120 */ + {.mk = { 0 }, .brk = { 0 } }, /* 121 */ + {.mk = { 0 }, .brk = { 0 } }, /* 122 */ + {.mk = { 0 }, .brk = { 0 } }, /* 123 */ + {.mk = { 0 }, .brk = { 0 } }, /* 124 */ + {.mk = { 0 }, .brk = { 0 } }, /* 125 */ + {.mk = { 0 }, .brk = { 0 } }, /* 126 */ + {.mk = { 0 }, .brk = { 0 } }, /* 127 */ + {.mk = { 0 }, .brk = { 0 } }, /* 128 */ + {.mk = { 0 }, .brk = { 0 } }, /* 129 */ + {.mk = { 0 }, .brk = { 0 } }, /* 12a */ + {.mk = { 0 }, .brk = { 0 } }, /* 12b */ + {.mk = { 0 }, .brk = { 0 } }, /* 12c */ + {.mk = { 0 }, .brk = { 0 } }, /* 12d */ + {.mk = { 0 }, .brk = { 0 } }, /* 12e */ + {.mk = { 0 }, .brk = { 0 } }, /* 12f */ + {.mk = { 0 }, .brk = { 0 } }, /* 130 */ + {.mk = { 0 }, .brk = { 0 } }, /* 131 */ + {.mk = { 0 }, .brk = { 0 } }, /* 132 */ + {.mk = { 0 }, .brk = { 0 } }, /* 133 */ + {.mk = { 0 }, .brk = { 0 } }, /* 134 */ + {.mk = { 0x65, 0 }, .brk = { 0 } }, /* 135 KP_DIVIDE */ + {.mk = { 0 }, .brk = { 0 } }, /* 136 */ + {.mk = { 0x74, 0 }, .brk = { 0 } }, /* 137 PRINTSCREEN */ + {.mk = { 0x31, 0 }, .brk = { 0xb1, 0 } }, /* 138* R-Alt */ + {.mk = { 0 }, .brk = { 0 } }, /* 139 */ + {.mk = { 0 }, .brk = { 0 } }, /* 13a */ + {.mk = { 0 }, .brk = { 0 } }, /* 13b */ + {.mk = { 0 }, .brk = { 0 } }, /* 13c */ + {.mk = { 0 }, .brk = { 0 } }, /* 13d */ + {.mk = { 0 }, .brk = { 0 } }, /* 13e */ + {.mk = { 0 }, .brk = { 0 } }, /* 13f */ + {.mk = { 0 }, .brk = { 0 } }, /* 140 */ + {.mk = { 0 }, .brk = { 0 } }, /* 141 */ + {.mk = { 0 }, .brk = { 0 } }, /* 142 */ + {.mk = { 0 }, .brk = { 0 } }, /* 143 */ + {.mk = { 0 }, .brk = { 0 } }, /* 144 */ + {.mk = { 0 }, .brk = { 0 } }, /* 145 */ + {.mk = { 0 }, .brk = { 0 } }, /* 146 */ + {.mk = { 0x4c, 0 }, .brk = { 0 } }, /* 147 Home */ + {.mk = { 0x4e, 0 }, .brk = { 0 } }, /* 148 Up */ + {.mk = { 0x52, 0 }, .brk = { 0 } }, /* 149 PageUp */ + {.mk = { 0 }, .brk = { 0 } }, /* 14a */ + {.mk = { 0x4b, 0 }, .brk = { 0 } }, /* 14b Left */ + {.mk = { 0 }, .brk = { 0 } }, /* 14c */ + {.mk = { 0x4d, 0 }, .brk = { 0 } }, /* 14d Right */ + {.mk = { 0 }, .brk = { 0 } }, /* 14e */ + {.mk = { 0x53, 0 }, .brk = { 0 } }, /* 14f End */ + {.mk = { 0x4a, 0 }, .brk = { 0 } }, /* 150 Down */ + {.mk = { 0x54, 0 }, .brk = { 0 } }, /* 151 PageDown */ + {.mk = { 0x4f, 0 }, .brk = { 0 } }, /* 152 Ins */ + {.mk = { 0x50, 0 }, .brk = { 0 } }, /* 153 Del */ + {.mk = { 0 }, .brk = { 0 } }, /* 154 */ + {.mk = { 0 }, .brk = { 0 } }, /* 155 */ + {.mk = { 0 }, .brk = { 0 } }, /* 156 */ + {.mk = { 0 }, .brk = { 0 } }, /* 157 */ + {.mk = { 0 }, .brk = { 0 } }, /* 158 */ + {.mk = { 0 }, .brk = { 0 } }, /* 159 */ + {.mk = { 0 }, .brk = { 0 } }, /* 15a */ + {.mk = { 0x33, 0 }, .brk = { 0 } }, /* 15b LGUI->Muhenkan (in emulator only) */ + {.mk = { 0x35, 0 }, .brk = { 0 } }, /* 15c RGUI->Henkan (in emulator only) */ + {.mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 15d APPLICATION->Kana (in emulator only) */ + {.mk = { 0 }, .brk = { 0 } }, /* 15e */ + {.mk = { 0 }, .brk = { 0 } }, /* 15f */ + {.mk = { 0 }, .brk = { 0 } }, /* 160 */ + {.mk = { 0 }, .brk = { 0 } }, /* 161 */ + {.mk = { 0 }, .brk = { 0 } }, /* 162 */ + {.mk = { 0 }, .brk = { 0 } }, /* 163 */ + {.mk = { 0 }, .brk = { 0 } }, /* 164 */ + {.mk = { 0 }, .brk = { 0 } }, /* 165 */ + {.mk = { 0 }, .brk = { 0 } }, /* 166 */ + {.mk = { 0 }, .brk = { 0 } }, /* 167 */ + {.mk = { 0 }, .brk = { 0 } }, /* 168 */ + {.mk = { 0 }, .brk = { 0 } }, /* 169 */ + {.mk = { 0 }, .brk = { 0 } }, /* 16a */ + {.mk = { 0 }, .brk = { 0 } }, /* 16b */ + {.mk = { 0 }, .brk = { 0 } }, /* 16c */ + {.mk = { 0 }, .brk = { 0 } }, /* 16d */ + {.mk = { 0 }, .brk = { 0 } }, /* 16e */ + {.mk = { 0 }, .brk = { 0 } }, /* 16f */ + {.mk = { 0 }, .brk = { 0 } }, /* 170 */ + {.mk = { 0 }, .brk = { 0 } }, /* 171 */ + {.mk = { 0 }, .brk = { 0 } }, /* 172 */ + {.mk = { 0 }, .brk = { 0 } }, /* 173 */ + {.mk = { 0 }, .brk = { 0 } }, /* 174 */ + {.mk = { 0 }, .brk = { 0 } }, /* 175 */ + {.mk = { 0 }, .brk = { 0 } }, /* 176 */ + {.mk = { 0 }, .brk = { 0 } }, /* 177 */ + {.mk = { 0 }, .brk = { 0 } }, /* 178 */ + {.mk = { 0 }, .brk = { 0 } }, /* 179 */ + {.mk = { 0 }, .brk = { 0 } }, /* 17a */ + {.mk = { 0 }, .brk = { 0 } }, /* 17b */ + {.mk = { 0 }, .brk = { 0 } }, /* 17c */ + {.mk = { 0 }, .brk = { 0 } }, /* 17d */ + {.mk = { 0 }, .brk = { 0 } }, /* 17e */ + {.mk = { 0 }, .brk = { 0 } }, /* 17f */ + {.mk = { 0 }, .brk = { 0 } }, /* 180 */ + {.mk = { 0 }, .brk = { 0 } }, /* 181 */ + {.mk = { 0 }, .brk = { 0 } }, /* 182 */ + {.mk = { 0 }, .brk = { 0 } }, /* 183 */ + {.mk = { 0 }, .brk = { 0 } }, /* 184 */ + {.mk = { 0 }, .brk = { 0 } }, /* 185 */ + {.mk = { 0 }, .brk = { 0 } }, /* 186 */ + {.mk = { 0 }, .brk = { 0 } }, /* 187 */ + {.mk = { 0 }, .brk = { 0 } }, /* 188 */ + {.mk = { 0 }, .brk = { 0 } }, /* 189 */ + {.mk = { 0 }, .brk = { 0 } }, /* 18a */ + {.mk = { 0 }, .brk = { 0 } }, /* 18b */ + {.mk = { 0 }, .brk = { 0 } }, /* 18c */ + {.mk = { 0 }, .brk = { 0 } }, /* 18d */ + {.mk = { 0 }, .brk = { 0 } }, /* 18e */ + {.mk = { 0 }, .brk = { 0 } }, /* 18f */ + {.mk = { 0 }, .brk = { 0 } }, /* 190 */ + {.mk = { 0 }, .brk = { 0 } }, /* 191 */ + {.mk = { 0 }, .brk = { 0 } }, /* 192 */ + {.mk = { 0 }, .brk = { 0 } }, /* 193 */ + {.mk = { 0 }, .brk = { 0 } }, /* 194 */ + {.mk = { 0 }, .brk = { 0 } }, /* 195 */ + {.mk = { 0 }, .brk = { 0 } }, /* 196 */ + {.mk = { 0 }, .brk = { 0 } }, /* 197 */ + {.mk = { 0 }, .brk = { 0 } }, /* 198 */ + {.mk = { 0 }, .brk = { 0 } }, /* 199 */ + {.mk = { 0 }, .brk = { 0 } }, /* 19a */ + {.mk = { 0 }, .brk = { 0 } }, /* 19b */ + {.mk = { 0 }, .brk = { 0 } }, /* 19c */ + {.mk = { 0 }, .brk = { 0 } }, /* 19d */ + {.mk = { 0 }, .brk = { 0 } }, /* 19e */ + {.mk = { 0 }, .brk = { 0 } }, /* 19f */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1a9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1aa */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ab */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ac */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ad */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ae */ + {.mk = { 0 }, .brk = { 0 } }, /* 1af */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1b9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ba */ + {.mk = { 0 }, .brk = { 0 } }, /* 1bb */ + {.mk = { 0 }, .brk = { 0 } }, /* 1bc */ + {.mk = { 0 }, .brk = { 0 } }, /* 1bd */ + {.mk = { 0 }, .brk = { 0 } }, /* 1be */ + {.mk = { 0 }, .brk = { 0 } }, /* 1bf */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1c9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ca */ + {.mk = { 0 }, .brk = { 0 } }, /* 1cb */ + {.mk = { 0 }, .brk = { 0 } }, /* 1cv */ + {.mk = { 0 }, .brk = { 0 } }, /* 1cd */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ce */ + {.mk = { 0 }, .brk = { 0 } }, /* 1cf */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1d9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1da */ + {.mk = { 0 }, .brk = { 0 } }, /* 1db */ + {.mk = { 0 }, .brk = { 0 } }, /* 1dc */ + {.mk = { 0 }, .brk = { 0 } }, /* 1dd */ + {.mk = { 0 }, .brk = { 0 } }, /* 1de */ + {.mk = { 0 }, .brk = { 0 } }, /* 1df */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1e9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ea */ + {.mk = { 0 }, .brk = { 0 } }, /* 1eb */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ec */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ed */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ee */ + {.mk = { 0 }, .brk = { 0 } }, /* 1ef */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f0 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f1 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f2 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f3 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f4 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f5 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f6 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f7 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f8 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1f9 */ + {.mk = { 0 }, .brk = { 0 } }, /* 1fa */ + {.mk = { 0 }, .brk = { 0 } }, /* 1fb */ + {.mk = { 0 }, .brk = { 0 } }, /* 1fc */ + {.mk = { 0 }, .brk = { 0 } }, /* 1fd */ + {.mk = { 0 }, .brk = { 0 } }, /* 1fe */ + {.mk = { 0 }, .brk = { 0 } } /* 1ff */ + // clang-format on +}; + #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -1664,6 +2206,10 @@ keyboard_at_set_scancode_set(void) case 0x03: keyboard_set_table(scancode_set3); break; + + case 0x8a: + keyboard_set_table(scancode_set8a); + break; } } @@ -1922,19 +2468,22 @@ keyboard_at_write(void *priv) break; case 0xf0: /* Get/set scancode set */ - kbc_at_dev_queue_add(dev, (val > 3) ? 0xfe : 0xfa, 0); switch (val) { case 0x00: + kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK */ keyboard_at_log("%s: Get scan code set [%02X]\n", dev->name, keyboard_mode); kbc_at_dev_queue_add(dev, keyboard_mode, 0); break; case 0x01 ... 0x03: + case 0x8a: + kbc_at_dev_queue_add(dev, 0xfa, 0); /* ACK */ keyboard_mode = val; keyboard_at_log("%s: Set scan code set [%02X]\n", dev->name, keyboard_mode); keyboard_at_set_scancode_set(); break; default: /* Fatal so any instance of anything attempting to set scan code > 3 can be reported to us. */ + kbc_at_dev_queue_add(dev, 0xfe, 0); /* Resend */ fatal("%s: Scan code set [%02X] invalid, resend\n", dev->name, val); dev->flags |= FLAG_CTRLDAT; dev->state = DEV_STATE_MAIN_WANT_IN; From 048a9409809b1dbefb1b424a817d6a0b52dfce57 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:41:08 +0900 Subject: [PATCH 03/82] Added a machine PS/55 model 5551T --- src/machine/m_ps2_mca.c | 260 +++++++++++++++++++++++++++++++++++- src/machine/machine_table.c | 40 ++++++ 2 files changed, 297 insertions(+), 3 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index cb83d9be7..fc2e3313b 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -67,6 +67,8 @@ #include <86box/port_92.h> #include <86box/serial.h> #include <86box/video.h> +#include <86box/vid_svga.h> +#include <86box/vid_vga.h> #include <86box/machine.h> #include <86box/plat_unused.h> @@ -103,6 +105,8 @@ static struct ps2_t { int pending_cache_miss; serial_t *uart; + + vga_t* mb_vga; } ps2; /*The model 70 type 3/4 BIOS performs cache testing. Since 86Box doesn't have any @@ -140,6 +144,7 @@ static struct ps2_t { static uint8_t ps2_cache[65536]; static int ps2_cache_valid[65536 / 8]; +static void mem_encoding_update(void); #ifdef ENABLE_PS2_MCA_LOG int ps2_mca_do_log = ENABLE_PS2_MCA_LOG; @@ -358,6 +363,61 @@ model_80_read(uint16_t port) return 0xff; } +static uint8_t +ps55_model_50t_read(uint16_t port) +{ + ps2_mca_log(" Read SysBrd %04X xx %04X:%04X\n", port, cs >> 4, cpu_state.pc); + switch (port) + { + case 0x100: + return ps2.planar_id & 0xff; + case 0x101: + return ps2.planar_id >> 8; + case 0x102: + return ps2.option[0]; + case 0x103: + uint8_t val = 0xff; + /* + I/O 103h - Bit 7-4: Memory Card ID (Connector 1 or 3) + Bit 3-0: Memory Card ID (Connector 2) + + Memory Card ID: 7h = 2 MB Memory Card 2 or 3 Installed + 5h = 4 MB Memory Card 2 Installed + */ + switch (mem_size / 1024) + { + case 2: + if (ps2.option[1] & 0x04) val = 0xff; + else val = 0x7f; + break; + case 4: + if (ps2.option[1] & 0x04) val = 0xff; + else val = 0x77; + break; + case 6: + if (ps2.option[1] & 0x04) val = 0x7f; + else val = 0x77; + break; + case 8: + default: + if (ps2.option[1] & 0x04) val = 0x5f; + else val = 0x77; + break; + } + ps2_mca_log(" Read MCA %04X %02X %04X:%04X mem_size = %d, ps2option1 = %2X\n", port, val, cs >> 4, cpu_state.pc, mem_size, ps2.option[1]); + return val; + case 0x104: + return ps2.option[2]; + case 0x105: + return ps2.option[3]; + case 0x106: + return ps2.subaddr_lo; + case 0x107: + return ps2.subaddr_hi; + } + return 0xff; +} + static void model_50_write(uint16_t port, uint8_t val) { @@ -655,6 +715,78 @@ model_80_write(uint16_t port, uint8_t val) } } +static void +ps55_model_50t_write(uint16_t port, uint8_t val)//pcem55 +{ + ps2_mca_log(" Write SysBrd %04X %02X %04X:%04X\n", port, val, cs >> 4, cpu_state.pc); + switch (port) + { + case 0x102: + lpt1_remove(); + serial_remove(ps2.uart); + if (val & 0x04) + { + if (val & 0x08) + serial_setup(ps2.uart, COM1_ADDR, COM1_IRQ); + else + serial_setup(ps2.uart, COM2_ADDR, COM2_IRQ); + } + if (val & 0x10) + { + switch ((val >> 5) & 3) + { + case 0: + lpt1_init(LPT_MDA_ADDR); + break; + case 1: + lpt1_init(LPT1_ADDR); + break; + case 2: + lpt1_init(LPT2_ADDR); + break; + default: + break; + } + } + ps2.option[0] = val; + break; + case 0x103: + ps2.option[1] = val; + break; + case 0x104: + if ((ps2.option[2] ^ val) & 1) { + mem_encoding_update(); + if (val & 1)/* Disable E0000 - E0FFF(Make 2 KB hole for Display Adapter) */ + { + ps2_mca_log("ROM E0000-E0FFF is disabled.\n"); + //mem_mapping_set_addr(&bios_mapping 0xe1000, 0x1f000); + mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + //mem_mapping_disable(&bios_mapping[0]); + } + else/* Enable E0000 - E0FFF for BIOS */ + { + ps2_mca_log("ROM E0000-E0FFF is enabled.\n"); + //mem_mapping_set_addr(&bios_mapping 0xe0000, 0x20000); + //mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED); + //mem_mapping_enable(&bios_mapping[0]); + } + } + ps2.option[2] = val; + break; + case 0x105: + ps2.option[3] = val; + break; + case 0x106: + ps2.subaddr_lo = val; + break; + case 0x107: + ps2.subaddr_hi = val; + break; + default: + break; + } +} + uint8_t ps2_mca_read(uint16_t port, UNUSED(void *priv)) { @@ -793,7 +925,16 @@ ps2_mca_write(uint16_t port, uint8_t val, UNUSED(void *priv)) if (!(ps2.setup & PS2_SETUP_IO)) ps2.planar_write(port, val); else if (!(ps2.setup & PS2_SETUP_VGA)) + { + if (ps2.mb_vga) + { + if (vga_isenabled(ps2.mb_vga)) + vga_disable(ps2.mb_vga); + if (val & 1) + vga_enable(ps2.mb_vga); + } ps2.pos_vga = val; + } else if (ps2.adapter_setup & PS2_ADAPTER_SETUP) mca_write(port, val); break; @@ -1150,7 +1291,27 @@ mem_encoding_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) } mem_encoding_update(); } - +static void +mem_encoding_write_ps55(uint16_t addr, uint8_t val, void* p) +{ + //ps2_mca_log(" Write Memory Encoding %04X %02X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + switch (addr) + { + case 0xe0: + ps2.mem_regs[0] = val; + break; + case 0xe1: + ps2.mem_regs[1] = val; + break; + default: + break; + } + mem_encoding_update(); + if (ps2.option[2] & 1) /* reset memstate for E0000 - E0FFFh hole */ + { + mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } +} static uint8_t mem_encoding_read_cached(uint16_t addr, UNUSED(void *priv)) { @@ -1311,7 +1472,7 @@ ps2_mca_board_model_70_type34_init(int is_type4, int slots) } if (gfxcard[0] == VID_INTERNAL) - device_add(&ps1vga_mca_device); + ps2.mb_vga = device_add(&ps1vga_mca_device); } static void @@ -1385,7 +1546,7 @@ ps2_mca_board_model_80_type2_init(void) } if (gfxcard[0] == VID_INTERNAL) - device_add(&ps1vga_mca_device); + ps2.mb_vga = device_add(&ps1vga_mca_device); ps2.split_size = 0; } @@ -1576,3 +1737,96 @@ machine_ps2_model_70_type4_init(const machine_t *model) return ret; } + +void +ps55_mca_board_model_50t_init() +{ + ps2_mca_board_common_init(); + + //mem_remap_top(256); + ps2.split_addr = mem_size * 1024; + /* The slot 5 is reserved for the Integrated Fixed Disk II (an internal ESDI hard drive). */ + mca_init(5); + device_add(&keyboard_ps2_mca_1_device); + + ps2.planar_read = ps55_model_50t_read; + ps2.planar_write = ps55_model_50t_write; + + device_add(&ps2_nvr_device); + + io_sethandler(0x00e0, 0x0002, mem_encoding_read, NULL, NULL, mem_encoding_write_ps55, NULL, NULL, NULL); + + ps2.mem_regs[1] = 2; + ps2.option[2] &= 0xfe; /* Bit 0: Disable E0000-E0FFFh (4 KB) */ + + //resize bios_mapping 0,1 + //mem_mapping_set_addr(&bios_mapping[0], 0xe0000, 0x1000); + //mem_mapping_set_exec(&bios_mapping[0], rom + (0x20000 & biosmask)); + //mem_mapping_set_addr(&bios_mapping[1], 0xe1000, 0x7000); + //mem_mapping_set_exec(&bios_mapping[1], rom + (0x21000 & biosmask)); + //mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x20000 & biosmask), MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM, 0); + //mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x23000 & biosmask), MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM, 0); + + mem_mapping_add(&ps2.split_mapping, + (mem_size + 256) * 1024, + 256 * 1024, + ps2_read_split_ram, + ps2_read_split_ramw, + ps2_read_split_raml, + ps2_write_split_ram, + ps2_write_split_ramw, + ps2_write_split_raml, + &ram[0xa0000], + MEM_MAPPING_INTERNAL, + NULL); + mem_mapping_disable(&ps2.split_mapping); + + if (mem_size > 8192) { + /* Only 8 MB supported on planar, create a memory expansion card for the rest */ + ps2_mca_mem_fffc_init(8); + } + + if (gfxcard[0] == VID_INTERNAL) + ps2.mb_vga = (vga_t *)device_add(&ps1vga_mca_device); +} + +int +machine_ps55_model_50t_init(const machine_t* model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ibmps55_m50t/38F6933.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + /* begin ps2 common init */ + machine_common_init(model); + + device_add(&fdc_at_ps55_device); + + dma16_init(); + ps2_dma_init(); + device_add(&ps_no_nmi_nvr_device); + pic2_init(); + + int pit_type = ((pit_mode == -1 && is486) || pit_mode == 1) ? PIT_8254_FAST : PIT_8254; + pit_ps2_init(pit_type); + + nmi_mask = 0x80; + + ps2.uart = device_add_inst(&ns16550_device, 1); + /* end ps2 common init */ + + /* + * Planar ID + * FFFAh - PS/55 model 5551-S0x, T0x (stage 1?) + * FFEEh - PS/55 model 5551-S1x, T1x (stage 2?) + * POST (P/N 38F6933) determination: FBxx -> 4 slots (error), xxEE -> 5 slots (ok), others -> 8 (error) + */ + ps2.planar_id = 0xffee; + ps55_mca_board_model_50t_init(); + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index a9d83f241..c005c9282 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -5468,6 +5468,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has IBM PS/55 5551-Sxx, Txx stage 2 firmware. */ + { + .name = "[MCA] IBM PS/55 model 5550-T", + .internal_name = "ibmps55_m50t", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps55_model_50t_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX | CPU_PKG_486BL, + .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_MCA, + .flags = MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 2048, + .max = 16384, + .step = 2048 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 386DX/486 machines */ /* Has AMIKey F KBC firmware. */ From d46121497c111acf42ac02c661d47fb229baa0b5 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:42:43 +0900 Subject: [PATCH 04/82] Added IBM Display Adapter II for PS/55 emulation --- src/video/CMakeLists.txt | 2 +- src/video/vid_ps55da2.c | 3153 ++++++++++++++++++++++++++++++++++++++ src/video/vid_svga.c | 22 +- src/video/vid_table.c | 2 + src/video/vid_vga.c | 34 + 5 files changed, 3209 insertions(+), 4 deletions(-) create mode 100644 src/video/vid_ps55da2.c diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 2f7607ad6..96d669ae1 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -27,7 +27,7 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c vid_tkd8001_ramdac.c vid_att20c49x_ramdac.c vid_s3.c vid_s3_virge.c vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_mga.c vid_nga.c vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c - vid_bochs_vbe.c) + vid_bochs_vbe.c vid_ps55da2.c ) if(G100) target_compile_definitions(vid PRIVATE USE_G100) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c new file mode 100644 index 000000000..13f823c83 --- /dev/null +++ b/src/video/vid_ps55da2.c @@ -0,0 +1,3153 @@ +/* + * 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. + * + * IBM PS/55 Display Adapter II emulation. + * + * Authors: Akamaki. + * + * Copyright 2024 Akamaki. + */ + +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/machine.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/mca.h> +#include <86box/rom.h> +#include <86box/plat.h> +#include <86box/thread.h> +#include <86box/video.h> +#include <86box/vid_ps55da2.h> +#include <86box/vid_svga.h> +#include <86box/vid_svga_render.h> +#include "cpu.h" + +#define DA2_FONTROM_PATH "roms/video/da2/PS55FNTJ.BIN" +#define DA2_FONTROM_SIZE 1024*1024 +#define DA2_MASK_MMIO 0x1ffff +#define DA2_MASK_GRAM 0x1ffff +#define DA2_MASK_CRAM 0xfff +#define DA2_MASK_GAIJIRAM 0x3ffff +#define DA2_PIXELCLOCK 58000000.0 +#define DA2_BLT_MEMSIZE 0x80 +#define DA2_BLT_REGSIZE 0x40 +#define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) +#define DA2_DEBUG_BLTLOG_MAX 256*1024 +#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe +#define DA2_DEBUG_BLT_USEDRESET 0xfefefe + +#define DA2_BLT_CIDLE 0 +#define DA2_BLT_CFILLRECT 1 +#define DA2_BLT_CFILLTILE 2 +#define DA2_BLT_CCOPYF 3 +#define DA2_BLT_CCOPYR 4 +#define DA2_BLT_CDONE 5 +#define DA2_BLT_CLOAD 6 +/* POS ID = 0xeffe : Display Adapter II, III, V */ +#define DA2_POSID_H 0xef +#define DA2_POSID_L 0xfe +/* + [Identification] + POS ID SYS ID + EFFFh * Display Adapter (PS/55 Model 5571-S0A) [Toledo] + E013h * Layout Display Terminal (PS/55-5571 RPQ model) [LDT] + EFFEh * Display Adapter II (I/O 3E0:0A = xx0x xxxx) [Atlas] + |- FFF2h Display Adapter B2 (I/O 3E0:0A = xx1x xxxx) (PS/55 Model 5530Z-SX) + |- FDFEh Display Adapter B2 (I/O 3E0:0A = xx1x xxxx) (PS/55 Model 5550-V2) + |- * Display Adapter III,V (I/O 3E0:0A = xx1x xxxx) + ECECh FF4Fh Display Adapter B1 (PS/55 Model 5531Z-SX) [Atlas-KENT] + |- * Display Adapter IV + ECCEh * Display Adapter IV + 901Fh * Display Adapter A2 + 901Dh * Display Adapter A1 [Atlas II] + 901Eh * Plasma Display Adapter + EFD8h * Display Adapter/J [Atlas-SP2] + + [Japanese DOS and Display Adapter compatibility] + | POS ID | Adapter Name | K3.31 | J4.04 | J5.02 | OS2 J1.3 | Win3 | + |------------|-----------------------------|:-----:|:-----:|:-----:|:--------:|:----:| + | EFFFh | Display Adapter | X | | | ? | | + | FFEDh | ? [Atlas EVT] | X | | | ? | | + | FFFDh | ? [LDT EVT] | X | | | ? | | + | EFFEh | Display Adapter II,III,V,B2 | X | X | X | X | X | + | E013h | ? [LDT] | X | X | X | X | | + | ECCEh | Display Adapter IV | | X | X | X | | + | ECECh | Display Adapter IV,B1 | | X | X | X | X | + | 9000-901Fh | Display Adapter A1,A2 | | X | X | | X | + | EFD8h | Display Adapter /J | | | X | X | X | +*/ +/* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ +#define OldLSI 0x20 /* DA-2 or DA-3,5 */ +#define Mon_ID3 0x10 +#define FontCard 0x08 /* ? */ +/* IO 3E0/3E1:0Ah Hardware Configuration Value H (imported from OS/2 DDK) */ +#define AddPage 0x08 /* ? */ +#define Mon_ID2 0x04 +#define Mon_ID1 0x02 +#define Mon_ID0 0x01 +/* Monitor ID (imported from OS/2 DDK 1.2) */ +//#define StarbuckC 0x0A //1010b IBM 8514, 9518 color 1040x768 +//#define StarbuckM 0x09 //1001b x grayscale +//#define Lark_B 0x02 //0010b IBM 9517 color 1040x768 +//#define Dallas 0x0B //1011b IBM 8515, 9515 color 1040x740 B palette +/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ +#define Page_One 0x06 /* 80000h 110b */ +#define Page_Two 0x05 /* 100000h 101b */ +#define Page_Four 0x03 /* 200000h 011b */ + +/* DA2 Registers (imported from OS/2 DDK) */ +#define AC_REG 0x3EE +#define AC_DMAE 0x80 +#define AC_FONT_SEL 0x40 +#define FONT_BANK 0x3EF +#define LS_INDEX 0x3E0 +#define LS_DATA 0x3E1 +#define LS_RESET 0x00 +#define LS_MODE 0x02 +#define LS_STATUS 0x03 /* added */ +#define LS_MMIO 0x08 /* added */ +#define LS_CONFIG1 0x0a +#define LS_CONFIG2 0x0b /* added */ +#define LF_INDEX 0x3e2 +#define LF_DATA 0x3e3 +#define LF_MMIO_SEL 0x08 /* added */ +#define LF_MMIO_ADDR 0x0A /* added */ +#define LF_MMIO_MODE 0x0B /* added */ +#define LC_INDEX 0x3E4 +#define LC_DATA 0x3E5 +#define LC_HORIZONTAL_TOTAL 0x00 +#define LC_H_DISPLAY_ENABLE_END 0x01 +#define LC_START_H_BLANKING 0x02 +#define LC_END_H_BLANKING 0x03 +#define LC_START_HSYNC_PULSE 0x04 +#define LC_END_HSYNC_PULSE 0x05 +#define LC_VERTICAL_TOTALJ 0x06 +#define LC_CRTC_OVERFLOW 0x07 +#define LC_PRESET_ROW_SCANJ 0x08 +#define LC_MAXIMUM_SCAN_LINE 0x09 +#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_ROW_CURSOR_LOC 0x0E +#define LC_CURSOR_LOC_LOWJ 0x0F +#define LC_COLUMN_CURSOR_LOC 0x0F +#define LC_VERTICAL_SYNC_START 0x10 +#define LC_LIGHT_PEN_HIGH 0x10 +#define LC_VERTICAL_SYNC_END 0x11 +#define LC_LIGHT_PEN_LOW 0x11 +#define LC_V_DISPLAY_ENABLE_END 0x12 +#define LC_OFFSET 0x13 +#define LC_UNDERLINE_LOCATION 0x14 +#define LC_START_VERTICAL_BLANK 0x15 +#define LC_END_VERTICAL_BLANK 0x16 +#define LC_LC_MODE_CONTROL 0x17 +#define LC_LINE_COMPAREJ 0x18 +#define LC_START_H_DISPLAY_ENAB 0x19 +#define LC_START_V_DISPLAY_ENAB 0x1A +#define LC_VIEWPORT_COMMAND 0x1B +#define LC_VIEWPORT_SELECT 0x1C +#define LC_VIEWPORT_PRIORITY 0x1D +#define LC_COMMAND 0x1E +#define LC_COMPATIBILITY 0x1F +#define LC_VIEWPORT_NUMBER 0x1F +#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 LG_INDEX 0x3EA +#define LG_DATA 0x3EB +#define LG_SET_RESETJ 0x00 +#define LG_ENABLE_SRJ 0x01 +#define LG_COLOR_COMPAREJ 0x02 +#define LG_DATA_ROTATION 0x03 +#define LG_READ_MAP_SELECT 0x04 +#define LG_MODE 0x05 +#define LG_COMPLEMENT 0x06 +#define LG_COLOR_DONT_CARE 0x07 +#define LG_BIT_MASK_LOW 0x08 +#define LG_BIT_MASK_HIGH 0x09 +#define LG_MAP_MASKJ 0x0A +#define LG_COMMAND 0x0B +#define LG_SET_RESET_2 0x10 + +#ifdef ENABLE_DA2_LOG +int da2_do_log = ENABLE_DA2_LOG; + +static void +da2_log(const char* fmt, ...) +{ + va_list ap; + + if (da2_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define da2_log(fmt, ...) +#endif +#ifndef RELEASE_BUILD +# define ENABLE_DA2_DEBUGBLT 1 +#endif + +typedef struct da2_t +{ + //mem_mapping_t vmapping; + mem_mapping_t cmapping; + + //uint8_t crtcreg; + uint8_t ioctl[16]; + uint8_t fctl[32]; + uint16_t crtc[128]; + uint8_t gdcreg[64]; + uint8_t reg3ee[16]; + int gdcaddr; + uint8_t attrregs[0x40]; + int attraddr, attrff; + int attr_palette_enable; + //uint8_t seqregs[64]; + int outflipflop; + int inflipflop; + int iolatch; + + int ioctladdr; + int fctladdr; + int crtcaddr; + + uint8_t miscout; + //int vidclock; + + uint32_t decode_mask; + uint32_t vram_max; + uint32_t vram_mask; + + uint32_t gdcla[8]; + //int gdcramlatched; + uint32_t gdcinput[8]; + uint32_t gdcsrc[8]; + uint32_t debug_vramold[8]; + + uint8_t dac_mask, dac_status; + int dac_read, dac_write, dac_pos; + int dac_r, dac_g; + + //IO 3DAh Input Status Register 2 + uint8_t cgastat; + + uint8_t plane_mask; + + int fb_only; + + int fast; + uint8_t colourcompare, colournocare; + int readmode, writemode, readplane; + uint8_t writemask; + uint32_t charseta, charsetb; + + uint8_t egapal[16]; + uint32_t pallook[512]; + PALETTE vgapal; + + int vtotal, dispend, vsyncstart, split, vblankstart; + int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; + int lowres, interlace; + int rowcount; + double clock; + uint32_t ma_latch, ca_adj; + + uint64_t dispontime, dispofftime; + pc_timer_t timer; + uint64_t da2const; + + uint8_t scrblank; + + int dispon; + int hdisp_on; + + uint32_t ma, maback, ca; + int vc; + int sc; + int linepos, vslines, linecountff, oddeven; + int con, cursoron, blink, blinkconf; + int scrollcache; + int char_width; + + int firstline, lastline; + int firstline_draw, lastline_draw; + int displine; + + /* Attribute Buffer E0000-E0FFFh (4 KB) */ + uint8_t *cram; + /* (cram size - 1) >> 3 = 0xFFF */ + //uint32_t cram_display_mask; + /* APA Buffer A0000-BFFFFh (128 KB) */ + uint8_t *vram; + /* addr >> 12 = xx000h */ + uint8_t *changedvram; + /* (vram size - 1) >> 3 = 0x1FFFF */ + uint32_t vram_display_mask; + uint32_t banked_mask; + + uint32_t write_bank, read_bank; + + int fullchange; + + //int video_res_x, video_res_y, video_bpp; + //int video_res_override; /*If clear then SVGA code will set above variables, if + // set then card code will*/ + //int frames, writelines; + + void (*render)(struct da2_t* da2); + //void (*recalctimings_ex)(struct da2_t* da2); + + //void (*video_out)(uint16_t addr, uint8_t val, void* p); + //uint8_t(*video_in) (uint16_t addr, void* p); + + /*If set then another device is driving the monitor output and the SVGA + card should not attempt to display anything */ + int override; + //void* p; + + /*Used to implement CRTC[0x17] bit 2 hsync divisor*/ + //int hsync_divisor; + + /* end VGA compatible regs*/ + struct + { + int enable; + mem_mapping_t mapping; + uint8_t ram[256 * 1024]; + uint8_t font[DA2_FONTROM_SIZE]; + } mmio; + + mem_mapping_t linear_mapping; + + uint32_t bank[2]; + uint32_t mask; + + int type; + + struct { + int bitshift_destr; + int raster_op; + uint8_t payload[DA2_BLT_MEMSIZE]; + int32_t reg[DA2_BLT_REGSIZE];//must be signed int + int32_t* debug_reg;//for debug + int debug_reg_ip;//for debug + int payload_addr; + pc_timer_t timer; + int64_t timerspeed; + int exec; + int indata; + int32_t destaddr; + int32_t srcaddr; + int32_t size_x, tile_w; + int32_t size_y; + int16_t destpitch; + int16_t srcpitch; + int32_t fcolor; + int32_t maskl, maskr; + int x, y; + } bitblt; + + FILE* mmdbg_fp; + FILE* mmrdbg_fp; + uint32_t mmdbg_vidaddr; + uint32_t mmrdbg_vidaddr; + + uint8_t pos_regs[8]; + svga_t *mb_vga; + + int vidsys_ena; + + int old_pos2; +} da2_t; + +void da2_recalctimings(da2_t* da2); +static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p); +void da2_bitblt_exec(void* p); +void da2_updatevidselector(da2_t* da2); +void da2_reset_ioctl(da2_t* da2); +static void da2_reset(void* priv); + +typedef union { + uint32_t d; + uint8_t b[4]; +} DA2_VidSeq32; + +typedef struct { + uint32_t p8[8]; +} pixel32; + +/* safety read for internal functions */ +uint32_t DA2_readvram_s(uint32_t addr, da2_t* da2) +{ + if (addr & ~da2->vram_mask) return -1; + return da2->vram[addr]; +} + +void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32* srcpx, da2_t* da2) +{ + uint32_t writepx[8]; + destaddr &= 0xfffffffe;/* align to word address to work bit shift correctly */ + //da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); + da2->changedvram[(da2->vram_display_mask & destaddr) >> 12] = changeframecount; + da2->changedvram[(da2->vram_display_mask & (destaddr+1)) >> 12] = changeframecount; + destaddr <<= 3; + /* read destination data with big endian order */ + for (int i = 0; i < 8; i++) + writepx[i] = DA2_readvram_s((destaddr + 24) | i, da2) + | (DA2_readvram_s((destaddr + 16) | i, da2) << 8) + | (DA2_readvram_s((destaddr + 8) | i, da2) << 16) + | (DA2_readvram_s((destaddr + 0) | i, da2) << 24); + + DA2_VidSeq32 mask32in; mask32in.d = (uint32_t)mask; + DA2_VidSeq32 mask32; mask32.d = 0; + mask32.b[3] = mask32in.b[0]; + mask32.b[2] = mask32in.b[1]; + mask32.d &= 0xffff0000; + for (int i = 0; i < 8; i++) + { + if (da2->bitblt.bitshift_destr > 0) + srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; + switch (da2->bitblt.raster_op) { + case 0x00: /* None */ + writepx[i] &= ~mask32.d; + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x01: /* AND */ + writepx[i] &= srcpx->p8[i] | ~mask32.d; + break; + case 0x02: /* OR */ + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x03: /* XOR */ + writepx[i] ^= srcpx->p8[i] & mask32.d; + break; + } + } + for (int i = 0; i < 8; i++) { + da2->vram[(da2->vram_mask & destaddr) | i] = (writepx[i] >> 24) & 0xff; + da2->vram[(da2->vram_mask & (destaddr + 8)) | i] = (writepx[i] >> 16) & 0xff; + } +} + +void DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t* da2) +{ + pixel32 srcpx; + //fill data with input color + for (int i = 0; i < 8; i++) + srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0;//read in word + + DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +/* +Param Desc +01 Color +03 Bit Shift +04 Select plane? +05 Dir(10 or 11) + Command?(40 or 48) +08 Mask Left +09 Mask Right +0A Plane Mask? +0B ROP?(8h or 200h + 0-3h) +0D +20 Exec (1) +21 ? +22 ? +23 Tile W +28 Tile H +29 Dest Addr +2A Src Addr +2B Tile Addr +33 Size W +35 Size H + +*/ +void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) +{ + pixel32 srcpx; + srcaddr &= 0xfffffffe; + srcaddr <<= 3; + for (int i = 0; i < 8; i++) + srcpx.p8[i] = DA2_readvram_s((srcaddr + 24) | i, da2) + | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) + | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) + | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24);//read in word + + DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +uint8_t pixel1tohex(uint32_t addr, int index, da2_t* da2) { + uint8_t pixeldata = 0; + for (int j = 0; j < 8; j++) { + if (da2->vram[(da2->vram_mask & (addr << 3)) | j] & (1 << (7 - index))) pixeldata++; + } + return pixeldata; +} +void print_pixelbyte(uint32_t addr, da2_t* da2) { + for (int i = 0; i < 8; i++) + { + da2_log("%X", pixel1tohex(addr, i, da2)); + } +} + +void da2_bitblt_load(da2_t* da2) +{ + uint32_t value32; + uint64_t value64; + //da2_log("BITBLT loading params\n"); + //da2_log("BitBlt memory:\n"); + //if (da2->bitblt.payload[0] != 0) + // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) + // { + // int i = j * 8; + // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + // da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + // } + int i = 0; + while (i < DA2_BLT_MEMSIZE) + { + if (da2->bitblt.reg[0x20] & 0x1) + break; + switch (da2->bitblt.payload[i]) { + case 0x88: + case 0x89: + case 0x95: + value32 = da2->bitblt.payload[i + 3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 2]; + //da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + i += 3; + break; + case 0x91: + value32 = da2->bitblt.payload[i + 5]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 4]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 2]; + //da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + i += 5; + break; + case 0x99: + value64 = da2->bitblt.payload[i + 7]; + value64 <<= 8; + value64 = da2->bitblt.payload[i + 6]; + value64 <<= 8; + value64 = da2->bitblt.payload[i + 5]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 4]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 3]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 2]; + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; + //da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + //da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + i += 7; + break; + case 0x00: + break; + default: + da2_log("da2_ParseBLT: Unknown PreOP!\n"); + break; + } + i++; + } + da2->bitblt.exec = DA2_BLT_CIDLE; + /* clear payload memory */ + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + da2->bitblt.payload_addr = 0; + /* [89] 20: 0001 (1) then execute payload */ + if (da2->bitblt.reg[0x20] & 0x1) + { +#ifdef ENABLE_DA2_DEBUGBLT + for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { + //if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); + } + for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { + da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; + } + da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * (da2->bitblt.debug_reg_ip + 1) - 1] = 0; + da2->bitblt.debug_reg_ip++; + if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; +#endif + da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f);//set bit shift + da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03;//01 AND, 03 XOR + da2_log("bitblt execute 05: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); + for (int i = 0; i <= 0xb; i++) + da2_log("%02x ", da2->gdcreg[i]); + da2_log("\n"); + + da2->bitblt.destaddr = da2->bitblt.reg[0x29]; + da2->bitblt.size_x = da2->bitblt.reg[0x33]; + da2->bitblt.size_y = da2->bitblt.reg[0x35]; + da2->bitblt.destpitch = da2->bitblt.reg[0x21]; + da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; + if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; + { + da2->bitblt.destaddr -= 2; + da2->bitblt.size_x += 1; + da2->bitblt.destpitch -= 2; + da2->bitblt.srcpitch -= 2; + } + da2->bitblt.fcolor = da2->bitblt.reg[0x0]; + da2->bitblt.maskl = da2->bitblt.reg[0x8]; + da2->bitblt.maskr = da2->bitblt.reg[0x9]; + da2->bitblt.x = 0; + da2->bitblt.y = 0; + da2->bitblt.exec = DA2_BLT_CDONE; + timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + + if (da2->bitblt.reg[0x2f] < 0x80)//MS Paint 3.1 will cause hang up in 256 color mode + { + da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); + da2->bitblt.exec = DA2_BLT_CDONE; + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {//Fill a rectangle (or draw a line) + da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); + da2->bitblt.exec = DA2_BLT_CFILLRECT; + da2->bitblt.destaddr += 2; + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) {//Tiling a rectangle ??(transfer tile data multiple times) os/2 only + da2->bitblt.exec = DA2_BLT_CFILLTILE; + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) {//Tiling a rectangle (transfer tile data multiple times) + da2->bitblt.exec = DA2_BLT_CFILLTILE; + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) {//Block transfer (range copy) + da2->bitblt.exec = DA2_BLT_CCOPYF; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; + da2->bitblt.destaddr += 2; + da2_log("copy block src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) {//Block copy but reversed direction + da2->bitblt.exec = DA2_BLT_CCOPYR; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + da2_log("copy blockR src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + //da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); + } + //do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle + while (timer_is_enabled(&da2->bitblt.timer) && da2->bitblt.exec != DA2_BLT_CDONE) + { + da2_bitblt_exec(da2); + } + } +} +void da2_bitblt_exec(void* p) +{ + da2_t* da2 = (da2_t*)p; + timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + //da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + switch (da2->bitblt.exec) + { + case DA2_BLT_CIDLE: + timer_disable(&da2->bitblt.timer); + break; + case DA2_BLT_CLOAD: + da2_bitblt_load(da2); + da2->bitblt.indata = 0; + break; + case DA2_BLT_CFILLRECT: + //da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + } + else if (da2->bitblt.x == 0) { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr += 2; + break; + case DA2_BLT_CFILLTILE: + int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + } + else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr += 2; + break; + case DA2_BLT_CCOPYF: + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + da2->bitblt.srcaddr += da2->bitblt.srcpitch + 2; + } + else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr += 2; + break; + case DA2_BLT_CCOPYR: + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr -= da2->bitblt.destpitch; + da2->bitblt.srcaddr -= da2->bitblt.srcpitch; + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + } + else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + break; + case DA2_BLT_CDONE: + //initialize regs with fefefefeh, clear regs with fefeh for debug dump + for (int i = 0; i < DA2_BLT_REGSIZE; i++) { + if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; + } + if(da2->bitblt.indata) da2->bitblt.exec = DA2_BLT_CLOAD; + else da2->bitblt.exec = DA2_BLT_CIDLE; + break; + } +} +void da2_out(uint16_t addr, uint16_t val, void *p) +{ + da2_t *da2 = (da2_t *)p; + int oldval; +/* +3E0 3E1 Sequencer Registers (undoc) +3E2 3E3 Font Registers (undoc) +3E4 3E5 CRT Control Registers (undoc) +3E8 3E9 Attribute Controller Registers (undoc) +3EA 3EB 3EC Graphics Contoller Registers +*/ + switch (addr) + { + case 0x3c6: /* PEL Mask */ + da2->dac_mask = val; + break; + case 0x3C7: /* Read Address */ + da2->dac_read = val; + da2->dac_pos = 0; + break; + case 0x3C8: /* Write Address */ + da2->dac_write = val; + da2->dac_read = val - 1; + da2->dac_pos = 0; + break; + case 0x3C9: /* Data */ + //da2_log("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI); + //da2_log("DS %X\n",DS); + da2->dac_status = 0; + da2->fullchange = changeframecount; + switch (da2->dac_pos) + { + case 0: + da2->dac_r = val; + da2->dac_pos++; + break; + case 1: + da2->dac_g = val; + da2->dac_pos++; + break; + case 2: + da2->vgapal[da2->dac_write].r = da2->dac_r; + da2->vgapal[da2->dac_write].g = da2->dac_g; + da2->vgapal[da2->dac_write].b = val; + //if (da2->ramdac_type == RAMDAC_8BIT) + // da2->pallook[da2->dac_write] = makecol32(da2->vgapal[da2->dac_write].r, da2->vgapal[da2->dac_write].g, da2->vgapal[da2->dac_write].b); + //else + da2->pallook[da2->dac_write] = makecol32((da2->vgapal[da2->dac_write].r & 0x3f) * 4, (da2->vgapal[da2->dac_write].g & 0x3f) * 4, (da2->vgapal[da2->dac_write].b & 0x3f) * 4); + da2->dac_pos = 0; + da2->dac_write = (da2->dac_write + 1) & 255; + break; + } + break; + case LS_INDEX: + da2->ioctladdr = val; + break; + case LS_DATA: + //da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->ioctladdr, val, cs >> 4, cpu_state.pc); + if (da2->ioctladdr > 0xf) return; + //if (da2->ioctl[da2->ioctladdr & 15] != val) + // da2_log("ioctl changed %x: %x -> %x %04X:%04X\n", da2->ioctladdr & 15, da2->ioctl[da2->ioctladdr & 15], val, cs >> 4, cpu_state.pc); + oldval = da2->ioctl[da2->ioctladdr]; + //if (da2->ioctladdr == 0x3) return;//monitor color + da2->ioctl[da2->ioctladdr] = val; + if (oldval != val) { + if (da2->ioctladdr == LS_RESET && val & 0x01) /* Mode register */ + da2_reset_ioctl(da2); + else if (da2->ioctladdr == LS_MODE && ((oldval ^ val) & 0x03)) /* Mode register */ + { + da2->fullchange = changeframecount; + da2_recalctimings(da2); + da2_updatevidselector(da2); + } + else if (da2->ioctladdr == LS_MMIO && (!(val & 0x01))) /* MMIO register */ + { + da2->bitblt.indata = 1; + if (da2->bitblt.exec == DA2_BLT_CIDLE) + { + da2->bitblt.exec = DA2_BLT_CLOAD; + timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + } + } + } + break; + case LF_INDEX: + da2->fctladdr = val; + break; + case LF_DATA: + //da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); + if (da2->fctladdr > 0x1f) return; + oldval = da2->fctl[da2->fctladdr]; + da2->fctl[da2->fctladdr] = val; + if (da2->fctladdr == 0 && oldval != val) + { + da2->fullchange = changeframecount; + da2_recalctimings(da2); + } + break; + case LC_INDEX: + da2->crtcaddr = val; + break; + case LC_DATA: + if (da2->crtcaddr > 0x1f) return; + if (!(da2->crtcaddr == LC_CURSOR_LOC_HIGH || da2->crtcaddr == LC_CURSOR_LOC_LOWJ)) + da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc); + if (!(da2->crtc[da2->crtcaddr] ^ val)) return; + switch (da2->crtcaddr) { + case LC_CRTC_OVERFLOW: + //return; + break; + case LC_MAXIMUM_SCAN_LINE: + if (!(da2->ioctl[LS_MODE] & 0x01)) val = 0; + break; + case LC_START_ADDRESS_HIGH: + //if (da2->crtc[0x1c] & 0x40) return; + break; + case LC_VERTICAL_TOTALJ: /* Vertical Total */ + case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ + case LC_V_DISPLAY_ENABLE_END: /* Vertical Display End Register */ + case LC_START_VERTICAL_BLANK: /* Start Vertical Blank Register */ + //val = 0x400; //for debugging bitblt + break; + case LC_VIEWPORT_SELECT: /* ViewPort Select? */ + //return; + break; + case LC_VIEWPORT_NUMBER: /* Compatibility? */ + break; + } + da2->crtc[da2->crtcaddr] = val; + switch (da2->crtcaddr) { + case LC_H_DISPLAY_ENABLE_END: + case LC_VERTICAL_TOTALJ: + case LC_MAXIMUM_SCAN_LINE: + case LC_START_ADDRESS_HIGH: + case LC_START_ADDRESS_LOW: + case LC_VERTICAL_SYNC_START: + case LC_V_DISPLAY_ENABLE_END: + case LC_START_VERTICAL_BLANK: + case LC_END_VERTICAL_BLANK: + case LC_VIEWPORT_PRIORITY: + da2->fullchange = changeframecount; + da2_recalctimings(da2); + break; + default: + break; + } + break; + case LV_PORT: + da2_log("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc); + if (!da2->attrff) + { + // da2->attraddr = val & 31; + da2->attraddr = val & 0x3f; + if ((val & 0x20) != (da2->attr_palette_enable & 0x20)) + { + da2->fullchange = 3; + da2->attr_palette_enable = val & 0x20; + da2_recalctimings(da2); + } + //da2_log("set attraddr: %X\n", da2->attraddr); + } + else + { + if ((da2->attraddr == LV_PANNING) && (da2->attrregs[LV_PANNING] != val)) + da2->fullchange = changeframecount; + if (da2->attrregs[da2->attraddr & 0x3f] != val) + da2_log("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrregs[da2->attraddr & 0x3f], val); + da2->attrregs[da2->attraddr & 0x3f] = val; + //da2_log("set attrreg %x: %x\n", da2->attraddr & 31, val); + if (da2->attraddr < 16) + da2->fullchange = changeframecount; + //if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr == 0x14 || da2->attraddr < 0x10) + if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) + { + for (int c = 0; c < 16; c++) + { + //if (da2->attrregs[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrregs[c] & 0xf) | ((da2->attrregs[0x14] & 0xf) << 4); + //else da2->egapal[c] = (da2->attrregs[c] & 0x3f) | ((da2->attrregs[0x14] & 0xc) << 4); + if (da2->attrregs[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = da2->attrregs[c] & 0xf; + else da2->egapal[c] = da2->attrregs[c] & 0x3f; + } + } + if (da2->attraddr == LV_COLOR_PLANE_ENAB) + { + if ((val & 0xff) != da2->plane_mask) + da2->fullchange = changeframecount; + da2->plane_mask = val & 0xff; + } + if (da2->attraddr == LV_CURSOR_CONTROL) + { + switch (val & 0x18) { + case 0x08://fast blink + da2->blinkconf = 0x10; + break; + case 0x18://slow blink + da2->blinkconf = 0x20; + break; + default://no blink + da2->blinkconf = 0xff; + break; + } + } + switch (da2->attraddr) + { + case LV_MODE_CONTROL: + case LV_ATTRIBUTE_CNTL: + case LV_COMPATIBILITY: + da2_recalctimings(da2); + break; + default: + break; + } + } + da2->attrff ^= 1; + break; + case LG_INDEX: + da2->gdcaddr = val; + break; + case LG_DATA: + //if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); + //if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI); + switch (da2->gdcaddr & 0x1f) + { + case LG_READ_MAP_SELECT: + da2->readplane = val & 0x7; + break; + case LG_MODE: + da2->writemode = val & 3; + break; + case LG_MAP_MASKJ: + da2->writemask = val & 0xff; + break; + case LG_COMMAND: + break; + case LG_SET_RESET_2: + da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); + return; + } + da2->gdcreg[da2->gdcaddr & 15] = val & 0xff; + break; + //case 0x3ed: /* used by Windows 3.1 display driver */ + // da2->gdcreg[5] = val & 0xff; + // break; + default: + da2_log("DA2? Out addr %03X val %02X\n", addr, val); + break; + } +} + +uint16_t da2_in(uint16_t addr, void *p) +{ + da2_t * da2 = (da2_t *)p; + //svga_t *svga = &da2->svga; + uint16_t temp; + +// if (addr != 0x3da) da2_log("IN gd5429 %04X\n", addr); + switch (addr) + { + case 0x3c3: + temp = 0; + break; + case 0x3c6: temp = da2->dac_mask; + break; + case 0x3c7: temp = da2->dac_status; + break; + case 0x3c8: temp = da2->dac_write; + break; + case 0x3c9: + da2->dac_status = 3; + switch (da2->dac_pos) + { + case 0: + da2->dac_pos++; + temp = da2->vgapal[da2->dac_read].r & 0x3f; + break; + case 1: + da2->dac_pos++; + temp = da2->vgapal[da2->dac_read].g & 0x3f; + break; + case 2: + da2->dac_pos = 0; + da2->dac_read = (da2->dac_read + 1) & 255; + temp = da2->vgapal[(da2->dac_read - 1) & 255].b & 0x3f; + break; + } + break; + case LS_INDEX: + temp = da2->ioctladdr; + break; + case LS_DATA: + //da2->ioctl[3] = 0x80;//3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) + if (da2->ioctladdr > 0xf) return 0xff; + temp = da2->ioctl[da2->ioctladdr]; + if (da2->ioctladdr == LS_STATUS) { /* Status register */ + //da2_log("Read 3E1 DAC status: %d, %d, %d\n", da2->vgapal[0].r, da2->vgapal[0].g, da2->vgapal[0].b); + //da2_log("attr palette: "); + //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->attrregs[i]); + //da2_log("\n"); + //da2_log("vram A0000h: "); + //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->vram[i]); + //da2_log("\n"); + //da2_log("vram B8000h: "); + //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->vram[0x18000 + i]); + //da2_log("\n"); + //da2_log("vram E0000h: "); + //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->cram[i]); + //da2_log("\n"); + if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 0x50 && da2->attrregs[LV_COMPATIBILITY] & 0x08) + temp &= 0x7F; /* Inactive when the RGB output voltage is high(or the cable is not connected to the color monitor). */ + else + temp |= 0x80; /* Active when the RGB output voltage is lowand the cable is connected to the color monitor. + If the cable or the monitor is wrong, it becomes inactive. */ + temp &= 0xf6;//idle + if (da2->bitblt.exec != DA2_BLT_CIDLE) + { + //da2_log("exec:%d\n", da2->bitblt.exec); + temp |= 0x08;//wait(bit 3 + bit 0) + //if (!da2->bitblt.timer.enabled) + //{ + // da2_log("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); + // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + //} + } + if (da2->bitblt.indata) + temp |= 0x01; + //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + } + //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + break; + case LF_INDEX: + temp = da2->fctladdr; + break; + case LF_DATA: + if (da2->fctladdr > 0x1f) return 0xff; + temp = da2->fctl[da2->fctladdr]; + break; + case LC_INDEX: + temp = da2->crtcaddr; + break; + case LC_DATA: + if (da2->crtcaddr > 0x1f) return 0xff; + temp = da2->crtc[da2->crtcaddr]; + break; + case LV_PORT: + temp = da2->attraddr | da2->attr_palette_enable; + break; + case 0x3E9: + if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this may equiv to 3ba / 3da Input Status Register 1 */ + { + if (da2->cgastat & 0x01) + da2->cgastat &= ~0x30; + else + da2->cgastat ^= 0x30; + temp = da2->cgastat; + } + else + temp = da2->attrregs[da2->attraddr]; + //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->attraddr, temp, cs >> 4, cpu_state.pc); + da2->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */ + break; + case LG_INDEX: + temp = da2->gdcaddr; + break; + case LG_DATA: + temp = da2->gdcreg[da2->gdcaddr & 0x1f]; + da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc); + break; + } + //da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + 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) +*/ +void da2_outb(uint16_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //da2_log("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); + da2->inflipflop = 0; + switch (addr) + { + case LS_DATA: + case LF_DATA: + case LC_DATA: + case LG_DATA: + if (da2->outflipflop) + { + /* out b(idx), out b(data), out b(data) */ + da2->iolatch |= (uint16_t)val << 8; + da2->outflipflop = 0; + } + else + {// + da2->iolatch = val; + da2->outflipflop = 1; + } + break; + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + default: + da2->iolatch = val; + da2->outflipflop = 0; + break; + } + da2_out(addr, da2->iolatch, da2); +} +void da2_outw(uint16_t addr, uint16_t val, void* p) +{ + //da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_t* da2 = (da2_t*)p; + da2->inflipflop = 0; + switch (addr) + { + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + da2_out(addr, val & 0xff, da2); + da2->iolatch = val >> 8; + da2_out(addr + 1, da2->iolatch, da2); + da2->outflipflop = 1; + break; + case LV_PORT: + da2->attrff = 0; + da2_out(addr, val & 0xff, da2); + da2_out(addr, val >> 8, da2); + da2->outflipflop = 0; + break; + case 0x3EC: + //da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_out(LG_DATA, val >> 8, da2); + break; + case 0x3ED: + da2->gdcaddr = LG_MODE; + da2_out(LG_DATA, val, da2); + break; + case LS_DATA: + case LF_DATA: + case LC_DATA: + case LG_DATA: + default: + da2_out(addr, val, da2); + da2->outflipflop = 0; + break; + case 0x3EE: + da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2->reg3ee[val & 0xff] = val >> 8; + break; + } +} +uint8_t da2_inb(uint16_t addr, void* p) +{ + uint8_t temp; + da2_t* da2 = (da2_t*)p; + da2->outflipflop = 0; + switch (addr) + { + case LC_DATA: + if (da2->inflipflop) + { + /* out b(idx), in b(low data), in b(high data) */ + temp = da2->iolatch >> 8; + da2->inflipflop = 0; + } + else + {// + da2->iolatch = da2_in(addr, da2); + temp = da2->iolatch & 0xff; + da2->inflipflop = 1; + } + break; + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + case LS_DATA: + case LF_DATA: + case LG_DATA: + default: + temp = da2_in(addr, da2) & 0xff; + da2->inflipflop = 0; + break; + } + //da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + return temp; +} +uint16_t da2_inw(uint16_t addr, void* p) +{ + //uint16_t temp; + da2_t* da2 = (da2_t*)p; + da2->inflipflop = 0; + da2->outflipflop = 0; + return da2_in(addr, da2); +} +/* IO 03DAh : Input Status Register 2 for DOSSHELL in DOS J4.0 */ +uint8_t da2_in_ISR(uint16_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + uint8_t temp = 0; + if (addr == 0x3da) { + if (da2->cgastat & 0x01) + da2->cgastat &= ~0x30; + else + da2->cgastat ^= 0x30; + temp = da2->cgastat; + } + //da2_log("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + return temp; +} + +void da2_out_ISR(uint16_t addr, uint8_t val, void* p) +{ + //da2_t* da2 = (da2_t*)p; + da2_log("DA2D Out %04X %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); +} + +/* +The IBM 5550 character mode addresses video memory between E0000h and E0FFFh. + [Character drawing] + SBCS: + 1 2 ... 13 + 1 | H.Grid + |---------------- + 2 | Space + 3 V| + .| + G| Font Pattern + r| (12x24 pixels) + i| + d| +26 |________________ +27 Space + ---------------- +28 Underscore ] + ---------------- >Cursor Position +29 ] + + DBCS: + 1 2 ... 13 1 2 ... 12 13 + 1 | H.Grid | H.Grid | + -|--------------------------|- + 2 | Space | Space | + -|--------------------------|- + 3 V| | |S + .| | |p + G| Font Pattern |a + r| (24x24 pixels) |c + i| | |e + d| | | +26 |_____________|____________| +27 | Space | Space + ------------------------------ +28 | Underscore | Underscore ] + ------------------------------ >Cursor Position +29 | | ] + + [Attributes] + Video mode 08h: + 7 6 5 4 3 2 1 0 + Blink |Under |HGrid |VGrid |Bright|Revers|FntSet|DBCS/SBCS| + + Video mode 0Eh: + -Blue |-Green|HGrid |VGrid |-Red |Revers|FntSet|DBCS/SBCS| + + Bit 1 switches the font bank to the Extended SBCS. DOS K3.x loads APL characters from $SYSEX24.FNT into it. + DOS Bunsho Program transfers 1/2 and 1/4 fonts fron the font ROM to the Extended SBCS. + This bit is not used for DBCS, but some apps set it as that column is right half of DBCS. + +[Font ROM Map (DA2)] +The Font ROM is accessed via 128 KB memory window located on A0000-BFFFFh. +I don't know how much data the actual Font ROM has. +Here information, I researched it by disassembling J-DOS. + +Bank 0 + 4800- * +Bank 1, 2, 3 + * - * +Bank 4 + * -0DB6Fh ( 4800-8DB6Fh;IBMJ 100-1F7Dh) : JIS X 0208 DBCS (24 x 24) +10000-16D1Fh (90000-96D1Fh;IBMJ 2000-2183h) : IBM Extended Characters +18000-1BFFFh (98000-9BFFFh;around IBMJ 21C7-22AAh) : JIS X 0201 SBCS (13 x 30) +1FD20- * +Bank 5 + * -0D09Fh (9FD20-AD09Fh;IBMJ 2384-2673h) : Gaiji 752 chs (maybe blank) +10000-13FFFh (B0000-B3FFFh;around IBMJ 271C-27FFh) : Extended SBCS (13 x 30) +14000-146FFh (B4000-B46FFh;IBMJ 2800-2818h) : Half-width box drawing characters (7 lines * 4 parts * 64 bytes) used by DOS Bunsho + (B9580-?;IBMJ 2930-295e?) : Full-width box drawing characters + + The signature 80h, 01h must be placed at Bank 0:1AFFEh to run OS/2 J1.3. + +[Gaiji RAM Map (DA2)] + Bank 0 00000-1FFFFh placed between A0000h-BFFFFh + 00000-1F7FFh(A0000-BF7FFh): Gaiji Non-resident (Kuten 103-114 ku,IBM: 2674-2ADBh) 1008 chs 128 bytes + 1F800-1FFFFh(BF800-BFFFFh): Gaiji Resident (SJIS: F040-F04Fh, IBM: 2384-2393h) 16 chs + + Bank 1 20000-3FFFFh placed between A0000h-BFFFFh + 20000-33FFFh(A0000-B3FFFh): Gaiji Resident (SJIS: F050-F39Ch, IBM: 2394-2613h) 640 chs + 34000-37FFFh(B4000-B7FFFh): Basic SBCS(00-FFh, ATTR bit 1 = off) + 38000-3AFFFh(B8000-BAFFFh): Gaiji Resident (SJIS: F39D-F3FCh, IBM: 2614-2673h) 96 chs + 3C000-3FFFFh(BC000-BFFFFh): Extended SBCS(00-FFh, ATTR bit 1 = on) + +[IBMJ code to Gaiji address conv tbl from DOS K3.3] + A B C + 2ADC, 2C5F, +5524 --> 8000 + 2614, 2673, +90EC --> B700 + 2384, 2613, +906C --> B3F0 + 0682, 1F7D, +0000 + + 8000 - 8183h 184h(388 characters) IBM Extended Characters + B3F0 - B75Fh 370h(880 characters) User-defined Characters +*/ + +/* Get character line pattern from jfont rom or gaiji volatile memory */ +uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void* p) { + da2_t* da2 = (da2_t*)p; + uint32_t font = 0; + int32_t fline = line - 2;//Start line of drawing character (line >= 1 AND line < 24 + 1 ) + if (code >= 0x8000 && code <= 0x8183) code -= 0x6000;//shift for IBM extended characters (I don't know how the real card works.) + if (code < DA2_FONTROM_SIZE / 72 && fline >= 0 && fline < 24) { + font = da2->mmio.font[code * 72 + fline * 3]; //1111 1111 + font <<= 8; //1111 1111 0000 0000 + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; //1111 1111 2222 0000 + font >>= 1; //0111 1111 1222 2000 + font <<= 4; //0111 1111 1222 2000 0000 + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; //0111 1111 1222 2000 2222 + font <<= 8; //0111 1111 1222 2000 2222 0000 0000 + font |= da2->mmio.font[code * 72 + fline * 3 + 2]; //0111 1111 1222 2000 2222 3333 3333 + font <<= 4; //0111 1111 1222 2000 2222 3333 3333 0000 + //font >>= 1;//put blank at column 1 (and 26) + } + else if (code >= 0xb000 && code <= 0xb75f) + { + //convert code->address in gaiji memory + code -= 0xb000; + code *= 0x80; + //code += 0xf800; + font = da2->mmio.ram[code + line * 4]; + font <<= 8; + font |= da2->mmio.ram[code + line * 4 + 1]; + font <<= 8; + font |= da2->mmio.ram[code + line * 4 + 2]; + font <<= 8; + font |= da2->mmio.ram[code + line * 4 + 3]; + } + else if (code > DA2_FONTROM_SIZE) + font = 0xffffffff; + else + font = 0; + return font; +} + +/* Reverse the bit order of attribute code IRGB to BGRI(used in Mode 3 and Cursor Color) */ +uint8_t IRGBtoBGRI(uint8_t attr) +{ + attr = ((attr & 0x01) << 7) | ((attr & 0x02) << 5) | ((attr & 0x04) << 3) | ((attr & 0x08) << 1); + return attr >>= 4; +} +/* Get the foreground color from the attribute byte */ +uint8_t getPS55ForeColor(uint8_t attr, da2_t* da2) +{ + uint8_t foreground = ~attr & 0x08;// 0000 1000 + foreground <<= 2; //0010 0000 + foreground |= ~attr & 0xc0;// 1110 0000 + foreground >>= 4;//0000 1110 + if (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;//bright color palette + return foreground; +} + +void da2_render_blank(da2_t* da2) +{ + int x, xx; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + + for (x = 0; x < da2->hdisp; x++) + { + for (xx = 0; xx < 13; xx++) ((uint32_t*)buffer32->line[da2->displine])[(x * 13) + xx + 32] = 0; + } +} +/* Display Adapter Mode 8, E Drawing */ +static void da2_render_text(da2_t* da2) +{ + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + + if (da2->fullchange) + { + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + int x; + int drawcursor; + uint8_t chr, attr; + int fg, bg; + uint32_t chr_dbcs; + int chr_wide = 0; + //da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); + for (x = 0; x < da2->hdisp; x += 13) + { + chr = da2->cram[(da2->ma) & da2->vram_display_mask]; + attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; + //if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); + if (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80)//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, da2); + 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 = ((da2->blink & 0x20) || (!(attr & 0x80))) ? fg : bg; + //if(chr!=0x20) da2_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, da2->egapal[fg], da2->pallook[da2->egapal[fg]]); + } + //Draw character + for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank + //draw -= 13; + // 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 = da2->cram[((da2->ma) + 2) & da2->vram_display_mask]; + chr_dbcs <<= 8; + chr_dbcs |= chr; + // Get the font pattern + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->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 = 0x3c000; + else + fontbase = 0x34000; + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font + font <<= 8; + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font + //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + } + } + // right half of DBCS + else + { + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + chr_wide = 0; + } + //Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. + if (da2->sc == 27 && attr & 0x40 && ~da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) {//Underscore only in monochrome mode + for (uint32_t n = 0; n < 13; n++) + p[n] = da2->pallook[da2->egapal[fg]];//under line (white) + } + //Column 1 (Vertical Line) + if (attr & 0x10) { + p[0] = da2->pallook[da2->egapal[(da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[LV_GRID_COLOR_0]) : 2]];//vertical line (white) + } + if (da2->sc == 0 && attr & 0x20 && ~da2->attrregs[LV_PAS_STATUS_CNTRL]) {//HGrid + for (uint32_t n = 0; n < 13; n++) + p[n] = da2->pallook[da2->egapal[(da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[LV_GRID_COLOR_0]) : 2]];//horizontal line (white) + } + //Drawing text cursor + drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); + if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) + { + int cursorwidth = (da2->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); + int cursorcolor = (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[LV_CURSOR_COLOR]) : 2;//Choose color 2 if mode 8 + fg = (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : ((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] == da2->pallook[da2->egapal[cursorcolor]] || da2->egapal[bg] == da2->egapal[cursorcolor]) + p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[fg]] : da2->pallook[da2->egapal[bg]]; + else + p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[cursorcolor]] : p[n]; + } + da2->ma += 2; + p += 13; + } + da2->ma &= da2->vram_display_mask; + //da2->writelines++; + } +} + +/* Display Adapter Mode 3 Drawing */ +static void da2_render_textm3(da2_t* da2) +{ + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + + if (da2->fullchange) + { + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + int x; + int drawcursor; + uint8_t chr, attr, extattr; + int fg, bg; + uint32_t chr_dbcs; + int chr_wide = 0; + //da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); + for (x = 0; x < da2->hdisp; x += 13) + { + chr = da2->vram[(0x18000 + (da2->ma)) & da2->vram_mask]; + attr = da2->vram[((0x18000 + (da2->ma)) + 1) & da2->vram_mask]; + extattr = da2->vram[((0x10000 + (da2->ma)) + 1) & da2->vram_mask]; + //if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (0x18000 + da2->ma << 1) & da2->vram_mask, chr, attr); + bg = attr >> 4; + //if (da2->blink) bg &= ~0x8; + //fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg; + fg = attr & 0xf; + fg = IRGBtoBGRI(fg); + bg = IRGBtoBGRI(bg); + //Draw character + for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank + // SBCS or DBCS left half + if (chr_wide == 0) { + if (extattr & 0x01) chr_wide = 1; + // 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 = da2->vram[(0x18000 + (da2->ma) + 2) & da2->vram_mask]; + chr_dbcs <<= 8; + chr_dbcs |= chr; + // Get the font pattern + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; + font <<= 1; + } + } + else { + // the char code is SBCS (ANK) + uint32_t fontbase; + fontbase = 0x34000; + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font + font <<= 8; + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font + //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + } + } + // right half of DBCS + else + { + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + chr_wide = 0; + } + //Drawing text cursor + drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); + if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) + { + //int cursorwidth = (da2->crtc[0x1f] & 0x20 ? 26 : 13); + //int cursorcolor = (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[0x1a]) : 2;//Choose color 2 if mode 8 + //fg = (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; + //bg = 0; + //if (attr & 0x04) {//Color 0 if reverse + // bg = fg; + // fg = 0; + //} + for (uint32_t n = 0; n < 13; n++) + p[n] = da2->pallook[da2->egapal[fg]];//under line (white) + } + da2->ma += 2; + p += 13; + } + da2->ma &= da2->vram_display_mask; + //da2->writelines++; + } +} + +void da2_render_color_4bpp(da2_t* da2) +{ + int changed_offset = da2->ma >> 12; + //da2_log("ma %x cf %x\n", da2->ma, changed_offset); + da2->plane_mask &= 0x0f;//safety + + if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) + { + int x; + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + //da2_log("d %X\n", da2->ma); + + for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 + { + uint8_t edat[8]; + uint8_t dat; + + //get 8 pixels from vram + da2->ma &= da2->vram_display_mask; + *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); + da2->ma += 1; + + dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)); + p[0] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)); + p[1] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)); + p[2] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)); + p[3] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)); + p[4] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)); + p[5] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)); + p[6] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)); + p[7] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + p += 8; + } + //da2->writelines++; + } +} + +void da2_render_color_8bpp(da2_t* da2) +{ + int changed_offset = da2->ma >> 12; + //da2_log("ma %x cf %x\n", da2->ma, changed_offset); + + if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) + { + int x; + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + //da2_log("d %X\n", da2->ma); + + for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 + { + uint8_t edat[8]; + uint8_t dat; + + //get 8 pixels from vram + da2->ma &= da2->vram_display_mask; + *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); + *(uint32_t*)(&edat[4]) = *(uint32_t*)(&da2->vram[(da2->ma << 3) + 4]); + da2->ma += 1; + + dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)) | + ((edat[4] >> 3) & (1 << 4)) | ((edat[5] >> 2) & (1 << 5)) | ((edat[6] >> 1) & (1 << 6)) | ((edat[7] >> 0) & (1 << 7)); + p[0] = da2->pallook[dat]; + dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)) | + ((edat[4] >> 2) & (1 << 4)) | ((edat[5] >> 1) & (1 << 5)) | ((edat[6] >> 0) & (1 << 6)) | ((edat[7] << 1) & (1 << 7)); + p[1] = da2->pallook[dat]; + dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)) | + ((edat[4] >> 1) & (1 << 4)) | ((edat[5] >> 0) & (1 << 5)) | ((edat[6] << 1) & (1 << 6)) | ((edat[7] << 2) & (1 << 7)); + p[2] = da2->pallook[dat]; + dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)) | + ((edat[4] >> 0) & (1 << 4)) | ((edat[5] << 1) & (1 << 5)) | ((edat[6] << 2) & (1 << 6)) | ((edat[7] << 3) & (1 << 7)); + p[3] = da2->pallook[dat]; + dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)) | + ((edat[4] << 1) & (1 << 4)) | ((edat[5] << 2) & (1 << 5)) | ((edat[6] << 3) & (1 << 6)) | ((edat[7] << 4) & (1 << 7)); + p[4] = da2->pallook[dat]; + dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)) | + ((edat[4] << 2) & (1 << 4)) | ((edat[5] << 3) & (1 << 5)) | ((edat[6] << 4) & (1 << 6)) | ((edat[7] << 5) & (1 << 7)); + p[5] = da2->pallook[dat]; + dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)) | + ((edat[4] << 3) & (1 << 4)) | ((edat[5] << 4) & (1 << 5)) | ((edat[6] << 5) & (1 << 6)) | ((edat[7] << 6) & (1 << 7)); + p[6] = da2->pallook[dat]; + dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)) | + ((edat[4] << 4) & (1 << 4)) | ((edat[5] << 5) & (1 << 5)) | ((edat[6] << 6) & (1 << 6)) | ((edat[7] << 7) & (1 << 7)); + p[7] = da2->pallook[dat]; + p += 8; + } + //da2->writelines++; + } +} + +void da2_updatevidselector(da2_t* da2) { + /* if VGA passthrough mode */ + da2_log("DA2 selector: %d\n", da2->ioctl[LS_MODE]); + if (da2->ioctl[LS_MODE] & 0x02) + { + da2->override = 1; + svga_set_override(da2->mb_vga, 0); + } + else + { + svga_set_override(da2->mb_vga, 1); + da2->override = 0; + } +} + + +void da2_recalctimings(da2_t* da2) +{ + double crtcconst; + double _dispontime, _dispofftime, disptime; + + da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff;//w + da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff;//w + da2->vsyncstart = da2->crtc[LC_VERTICAL_SYNC_START] & 0xfff;//w + da2->split = da2->crtc[LC_LINE_COMPAREJ] & 0xfff;//w Line Compare + da2->split = 0xfff; + da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff;//w + da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; + + if (da2->crtc[LC_START_H_DISPLAY_ENAB] & 1) { + da2->hdisp--; + da2->dispend -= 29; + } + else { + //da2->vtotal += 2; + da2->dispend--; + //da2->vsyncstart++; + //da2->split++; + //da2->vblankstart++; + //da2->hdisp--; + } + + da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; + da2->htotal += 1; + + da2->rowoffset = da2->crtc[LC_OFFSET];//number of bytes in a scanline + + da2->clock = da2->da2const; + + da2->lowres = da2->attrregs[LC_VERTICAL_SYNC_START] & 0x40; + + da2->interlace = 0; + + //da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b + da2->ca_adj = 0; + + da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE]; + + da2->hdisp_time = da2->hdisp; + da2->render = da2_render_blank; + //determine display mode + //if (da2->attr_palette_enable && (da2->attrregs[0x1f] & 0x08)) + if (da2->attrregs[LV_COMPATIBILITY] & 0x08) + { + //if (da2->ioctl[0] & 0x01)//256 color mode + //{ + // da2_log("Set videomode to PS/55 8 bpp graphics.\n"); + // da2->vram_display_mask = 0x1ffff; + // da2->render = da2_render_color_8bpp; + //} + //else + if (!(da2->ioctl[LS_MODE] & 0x01)) {//16 color graphics mode + da2->hdisp *= 16; + da2->char_width = 13; + da2->hdisp_old = da2->hdisp; + //if (da2->plane_mask == 0x01) {//PS/55 monochrome + // da2_log("Set videomode to PS/55 Monochrome graphics.\n"); + // //da2->render = da2_render_mono; + // da2->render = da2_render_color_4bpp; + // da2->vram_display_mask = 0x1ffff; + //} + if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) {//PS/55 256 color + da2_log("Set videomode to PS/55 8 bpp graphics.\n"); + da2->render = da2_render_color_8bpp; + da2->vram_display_mask = DA2_MASK_GRAM; + } + else {//PS/55 8-color + da2_log("Set videomode to PS/55 4 bpp graphics.\n"); + da2->vram_display_mask = DA2_MASK_GRAM; + da2->render = da2_render_color_4bpp; + } + } + else {//text mode + if (da2->attrregs[LV_ATTRIBUTE_CNTL] & 1) {//PS/55 Mode 03 + da2_log("Set videomode to PS/55 Mode 03 text.\n"); + da2->render = da2_render_textm3; + da2->vram_display_mask = DA2_MASK_CRAM; + } + else {//PS/55 text(color/mono) + da2_log("Set videomode to PS/55 Mode 8/E text.\n"); + da2->render = da2_render_text; + da2->vram_display_mask = DA2_MASK_CRAM; + } + da2->hdisp *= 13; + da2->hdisp_old = da2->hdisp; + da2->char_width = 13; + } + } + else + { + da2_log("Set videomode to blank.\n"); + } + //if (!da2->scrblank && da2->attr_palette_enable) + //{ + //da2->render = da2_draw_text; + //} + + // da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); + + /*da2->char_width = 13;*///PS55TEXT = 13, GFX = 16 + //if (da2->recalctimings_ex) + // da2->recalctimings_ex(da2); + + if (da2->vblankstart < da2->dispend) + da2->dispend = da2->vblankstart; + + crtcconst = da2->clock * da2->char_width; + + disptime = da2->htotal; + _dispontime = da2->hdisp_time; + + da2_log("Disptime %f dispontime %f hdisp %i\n", disptime, _dispontime, da2->hdisp); + //if (da2->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; } + _dispofftime = disptime - _dispontime; + _dispontime *= crtcconst; + _dispofftime *= crtcconst; + + da2->dispontime = (uint64_t)_dispontime; + da2->dispofftime = (uint64_t)_dispofftime; + if (da2->dispontime < TIMER_USEC) + da2->dispontime = TIMER_USEC; + if (da2->dispofftime < TIMER_USEC) + da2->dispofftime = TIMER_USEC; + da2_log("da2 horiz total %i display end %i vidclock %f\n",da2->crtc[0],da2->crtc[1],da2->clock); + // da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart); + // da2_log("total %f on %i cycles off %i cycles frame %i sec %i\n",disptime*crtcconst,da2->dispontime,da2->dispofftime,(da2->dispontime+da2->dispofftime)*da2->vtotal,(da2->dispontime+da2->dispofftime)*da2->vtotal*70); + + // da2_log("da2->render %08X\n", da2->render); +} + +uint8_t da2_mca_read(int port, void *p) +{ + da2_t *da2 = (da2_t *)p; + return da2->pos_regs[port & 7]; +} + +static void da2_mapping_update(da2_t *da2) +{ + if (!((da2->pos_regs[2] ^ da2->old_pos2) & 1)) return; + da2->old_pos2 = da2->pos_regs[2]; + //da2_recalc_mapping(da2); + if (da2->pos_regs[2] & 0x01) + { + da2_log("DA2 enable registers\n"); + for (int i = 0; i < 8; i++) + da2_log("DA2 POS[%d]: %x\n", i, da2->pos_regs[i]); + io_sethandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_sethandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_sethandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); + mem_mapping_enable(&da2->cmapping); + mem_mapping_enable(&da2->mmio.mapping); + timer_enable(&da2->timer); + } + else + { + da2_log("DA2 disable registers\n"); + timer_disable(&da2->timer); + mem_mapping_disable(&da2->cmapping); + mem_mapping_disable(&da2->mmio.mapping); + io_removehandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_removehandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_removehandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); + } +} + +void da2_mca_write(int port, uint8_t val, void *p) +{ + da2_t *da2 = (da2_t *)p; + + da2_log("da2_mca_write: port=%04x val=%02x\n", port, val); + + if (port < 0x102) + return; + da2->pos_regs[port & 7] = val; + + da2_mapping_update(da2); +} + +static uint8_t da2_mca_feedb(void* priv) +{ + const da2_t* da2 = (da2_t*)priv; + + return da2->pos_regs[2] & 0x01; +} + +static void da2_mca_reset(void *p) +{ + da2_t *da2 = (da2_t *)p; + da2_reset(da2); + da2_mca_write(0x102, 0, da2); +} +// +static void da2_gdcropB(uint32_t addr, da2_t* da2) { + for (int i = 0; i < 8; i++) { + if (da2->writemask & (1 << i)) { + //da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW]); + switch (da2->gdcreg[LG_COMMAND] & 0x03) + { + case 0: /*Set*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 1: /*AND*/ + //da2->vram[addr | i] = (da2->gdcinput[i] | ~da2->gdcreg[LG_BIT_MASK_LOW]) & da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 2: /*OR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 3: /*XOR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) ^ da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + } + } + } +} +static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t* da2) { + uint8_t bitmask_l = bitmask & 0xff; + uint8_t bitmask_h = bitmask >> 8; + for (int i = 0; i < 8; i++) { + if (da2->writemask & (1 << i)) { + //da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]); + switch (da2->gdcreg[LG_COMMAND] & 0x03) + { + case 0: /*Set*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l); + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h); + da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 1: /*AND*/ + //da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i]; + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 2: /*OR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i]; + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 3: /*XOR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i]; + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + } + } + } +} + +static uint8_t da2_mmio_read(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + addr &= DA2_MASK_MMIO; + + if (da2->ioctl[LS_MMIO] & 0x10) { + if (da2->fctl[LF_MMIO_SEL] == 0x80) + //linear access + addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17); + else + { + //64k bank switch access + uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; + index <<= 8; + index |= da2->fctl[LF_MMIO_ADDR]; + addr += index * 0x40; + } + //da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { + case 0xb0://Gaiji RAM + addr &= DA2_MASK_GAIJIRAM;//safety access + //da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]); + return da2->mmio.ram[addr]; + break; + case 0x10://Font ROM + //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); + if (addr > DA2_FONTROM_SIZE) return 0xff; + return da2->mmio.font[addr]; + break; + default: + return 0xff;//invalid memory access + break; + } + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 or 256 color mode + { + cycles -= video_timing_read_b; + //readmode 1 + //da2_log("da2_rp: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->readplane, addr); + for (int i = 0; i < 8; i++) + da2->gdcla[i] = da2->vram[(addr << 3) | i];//read in byte + //da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read in word + //da2->gdcramlatched = 1; + //da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); + if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 + uint8_t ret = 0; + + for (int i = 0; i < 8; i++) + { + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register + ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xff : 0); + } + return ~ret; + } + else return da2->gdcla[da2->readplane]; + } + else //text mode 3 + { + cycles -= video_timing_read_b; + return da2->vram[addr]; + } +} +static uint16_t da2_mmio_readw(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + //da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + if (da2->ioctl[LS_MMIO] & 0x10) { + return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + { + cycles -= video_timing_read_w; + addr &= DA2_MASK_MMIO; + for (int i = 0; i < 8; i++) + da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read vram into latch + //da2->gdcramlatched = 1; + ////debug + //if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) + //{ + // fprintf(da2->mmrdbg_fp, "\nR %x ", addr); + // for (int i = 0; i <= 0xb; i++) + // fprintf(da2->mmrdbg_fp, "%02x ", da2->gdcreg[i]); + //} + //for (int i = 0; i < 16; i++) + //{ + // int pixeldata = 0; + // if (da2->gdcla[da2->readplane] & (1 << (15 - i))) pixeldata = 1; + // fprintf(da2->mmrdbg_fp, "%X", pixeldata); + //} + //da2->mmrdbg_vidaddr = addr; + //// + + if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 + uint16_t ret = 0; + + for (int i = 0; i < 8; i++) + { + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register + ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xffff : 0); + } + return ~ret; + } + else + { + //da2_log("da2_Rw: %05x=%04x\n", addr, da2->gdcla[da2->readplane]); + return da2->gdcla[da2->readplane]; + } + } + else { + return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); + } +} + +static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //da2_log("da2_mmio_write %x %x\n", addr, val); + if ((addr & ~DA2_MASK_MMIO) != 0xA0000) return; + addr &= DA2_MASK_MMIO; + + if (da2->ioctl[LS_MMIO] & 0x10) { + //if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI); + //Gaiji RAM + if (da2->fctl[LF_MMIO_SEL] == 0x80) + addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17);//xxxy yyyy yyyy yyyy yyyy + else + { + uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; + index <<= 8; + index |= da2->fctl[LF_MMIO_ADDR]; + addr += index * 0x40; + } + switch (da2->fctl[LF_MMIO_MODE]) { + case 0xb0://Gaiji RAM 1011 0000 + addr &= DA2_MASK_GAIJIRAM;//safety access + da2->mmio.ram[addr] = val; + break; + case 0x10://Font ROM 0001 0000 + //Read-Only + break; + case 0x00: + //da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); + addr &= 0x7f;//OS/2 write addr 1cf80-1cfc3, val xx + if (addr >= DA2_BLT_MEMSIZE) + { + da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + return; + } + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_addr++; + break; + default: + da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + break; + } + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + { + uint8_t wm = da2->writemask; + //da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); + //debug + //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + //{ + //if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) + //{ + // fprintf(da2->mmdbg_fp, "\nB %x ", addr); + // for (int i = 0; i <= 0xb; i++) + // fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + //} + //for (int i = 0; i < 8; i++) + //{ + // int pixeldata = 0; + // if (val & (1 << (7 - i))) pixeldata = (da2->writemask & 0xf); + // fprintf(da2->mmdbg_fp, "%X", pixeldata); + //} + //da2->mmdbg_vidaddr = addr; + //} + + cycles -= video_timing_write_b; + + da2->changedvram[addr >> 12] = changeframecount; + addr <<= 3; + + //if (GCLATCHCOND) { + //if (da2->writemode == 2) { + for (int i = 0; i < 8; i++) + da2->gdcsrc[i] = da2->gdcla[i];//use latch + //} + //else { + // for (int i = 0; i < 8; i++) + // da2->gdcsrc[i] = da2->vram[addr | i];//read in byte from vram + //} + //da2->gdcramlatched = 0; + //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); + //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); + + if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; + else da2->gdcinput[i] = val; + da2_gdcropB(addr, da2); + return; + } + + switch (da2->writemode) + { + case 2: + //case 1: + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) da2->vram[addr | i] = da2->gdcsrc[i]; + break; + case 0: + if (da2->gdcreg[LG_DATA_ROTATION] & 7) + val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; + if (da2->gdcreg[LG_BIT_MASK_LOW] == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) da2->vram[addr | i] = val; + } + else + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + else da2->gdcinput[i] = val; + + for (int i = 0; i < 8; i++) + da2->debug_vramold[i] = da2->vram[addr | i];//use latch + da2_gdcropB(addr, da2); + //for (int i = 0; i < 8; i++) + // da2_log("\tsrc %02x in %02x bitm %02x mod %x rop %x: %02x -> %02x\n", da2->gdcsrc[i], da2->gdcinput[i], da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch + //// da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); + } + break; + //case 2: + case 1: + if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + } + else + { + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); + da2_gdcropB(addr, da2); + } + break; + case 3: + if (da2->gdcreg[LG_DATA_ROTATION] & 7) + val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; + wm = da2->gdcreg[LG_BIT_MASK_LOW]; + da2->gdcreg[LG_BIT_MASK_LOW] &= val; + + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + da2_gdcropB(addr, da2); + da2->gdcreg[LG_BIT_MASK_LOW] = wm; + break; + } + //da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); + } + else// mode 3h text + { + cycles -= video_timing_write_b; + da2->vram[addr] = val; + da2->fullchange = 2; + } +} +uint16_t rightRotate(uint16_t data, uint8_t count) +{ + return (data >> count) | (data << (sizeof(data) * 8 - count)); +} +static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + uint8_t wm = da2->writemask; + uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + bitmask <<= 8; + bitmask |= (uint16_t)da2->gdcreg[LG_BIT_MASK_LOW]; + //debug + //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + //{ + //if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) + //{ + // fprintf(da2->mmdbg_fp, "\nW %x ", addr); + // for (int i = 0; i <= 0xb; i++) + // fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + //} + //for (int i = 0; i < 16; i++) + //{ + // int pixeldata = 0; + // if (val & (1 << (15 - i))) pixeldata = (da2->writemask & 0xf); + // fprintf(da2->mmdbg_fp, "%X", pixeldata); + //} + //da2->mmdbg_vidaddr = addr; + //} + //cycles -= video_timing_write_w; + //cycles_lost += video_timing_write_w; + + //da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); + //da2_log("da2_gcW %05X %02X %04X:%04X esdi %04X:%04X dssi %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); + + da2->changedvram[addr >> 12] = changeframecount; + da2->changedvram[(addr + 1) >> 12] = changeframecount; + addr <<= 3; + + //if (((da2->gdcreg[LG_COMMAND] & 0x03) || da2->writemode == 2) && da2->writemode != 1) { + //if (GCLATCHCOND) { + //if (da2->writemode == 2) { + for (int i = 0; i < 8; i++) + da2->gdcsrc[i] = da2->gdcla[i];//use latch + //} + //else { + // for (int i = 0; i < 8; i++) + // da2->gdcsrc[i] = (uint16_t)(da2->vram[addr | i]) | ((uint16_t)(da2->vram[(addr + 8) | i]) << 8);//read in word + //} + //da2->gdcramlatched = 0; + + if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; + else da2->gdcinput[i] = val; + da2_gdcropW(addr, bitmask, da2); + return; + } + //da2_log("da2_Ww m%02x r%02x %05x:%04x=%02x%02x%02x%02x,%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] + // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); + switch (da2->writemode)// writemode 0 or 2 rop(0b) 0 or 3 + { + case 2: + //case 1: + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + { + da2->vram[addr | i] = da2->gdcsrc[i] & 0xff; + da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; + } + break; + //case 2:win + + case 0: + if (da2->gdcreg[LG_DATA_ROTATION] & 15) + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work + if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + { + da2->vram[addr | i] = val & 0xff; + da2->vram[(addr + 8) | i] = val >> 8; + } + } + else + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + else da2->gdcinput[i] = val; + + //for (int i = 0; i < 8; i++)//draft20240722 0211 + // da2->gdcla[i] = 0;//read in word + da2_gdcropW(addr, bitmask, da2); + // da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); + } + break; + //case 2: + case 1: + if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + { + uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + da2->vram[addr | i] = wdata & 0xff; + da2->vram[(addr + 8) | i] = wdata >> 8; + } + } + else + { + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); + da2_gdcropW(addr, bitmask, da2); + } + break; + case 3: + if (da2->gdcreg[LG_DATA_ROTATION] & 15) + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work + wm = bitmask; + bitmask &= val; + + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + da2_gdcropW(addr, bitmask, da2); + bitmask = wm; + break; + } + //da2_log("%02x%02x%02x%02x,%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] + // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); +} +static void da2_mmio_writew(uint32_t addr, uint16_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //if ((addr & ~0x1ffff) != 0xA0000) return; + if (da2->ioctl[LS_MMIO] & 0x10) { + //da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + da2_mmio_write(addr, val & 0xff, da2); + da2_mmio_write(addr + 1, val >> 8, da2); + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + { + addr &= DA2_MASK_MMIO; + //return; + //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + da2_mmio_gc_writeW(addr, val, da2); + } + else {//mode 3h text + //if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); + //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + da2_mmio_write(addr, val & 0xff, da2); + da2_mmio_write(addr + 1, val >> 8, da2); + } +} + +static void da2_code_write(uint32_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //if ((addr & ~0xfff) != 0xE0000) return; + addr &= DA2_MASK_CRAM; + da2->cram[addr] = val; + da2->fullchange = 2; +} +static void da2_code_writeb(uint32_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //da2_log("DA2_code_writeb: Write to %x, val %x\n", addr, val); + cycles -= video_timing_write_b; + da2_code_write(addr, val, da2); +} +static void da2_code_writew(uint32_t addr, uint16_t val, void* p) +{ + //da2_log("DA2_code_writew: Write to %x, val %x\n", addr, val); + da2_t* da2 = (da2_t*)p; + cycles -= video_timing_write_w; + da2_code_write(addr, val & 0xff, da2); + da2_code_write(addr + 1, val >> 8, da2); +} + +static uint8_t da2_code_read(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + if ((addr & ~DA2_MASK_CRAM) != 0xE0000) return 0xff; + addr &= DA2_MASK_CRAM; + return da2->cram[addr]; +} +static uint8_t da2_code_readb(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + cycles -= video_timing_read_b; + return da2_code_read(addr, da2); +} +static uint16_t da2_code_readw(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + cycles -= video_timing_read_w; + return da2_code_read(addr, da2) | (da2_code_read(addr + 1, da2) << 8); + //return 0; +} + +void da2_doblit(int y1, int y2, int wx, int wy, da2_t* da2) +{ + 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; +} + +void da2_poll(void* priv) +{ + da2_t* da2 = (da2_t*)priv; + int x; + + if (!da2->linepos) + { + timer_advance_u64(&da2->timer, da2->dispofftime); + // if (output) printf("Display off %f\n",vidtime); + da2->cgastat |= 1; + da2->linepos = 1; + + if (da2->dispon) + { + da2->hdisp_on = 1; + + da2->ma &= da2->vram_display_mask; + if (da2->firstline == 2000) + { + da2->firstline = da2->displine; + video_wait_for_buffer(); + } + + //RENDER + if (!da2->override) + da2->render(da2); + + if (da2->lastline < da2->displine) + da2->lastline = da2->displine; + } + + //da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); + da2->displine++; + if (da2->interlace) + da2->displine++; + if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) + { + //da2_log("Vsync off at line %i\n",displine); + da2->cgastat &= ~8; + } + da2->vslines++; + if (da2->displine > 1200) + da2->displine = 0; + // da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], + // displine, vc, ma); + } + else + { + // da2_log("VC %i ma %05X\n", da2->vc, da2->ma); + timer_advance_u64(&da2->timer, da2->dispontime); + + // if (output) printf("Display on %f\n",vidtime); + if (da2->dispon) + da2->cgastat &= ~1; + da2->hdisp_on = 0; + + da2->linepos = 0; + if (da2->sc == (da2->crtc[LC_VERTICAL_SYNC_END] & 31)) + da2->con = 0; + if (da2->dispon) + { + if (da2->sc == da2->rowcount) + { + da2->linecountff = 0; + da2->sc = 0; + + da2->maback += (da2->rowoffset << 1);// color = 0x50(80), mono = 0x40(64) + if (da2->interlace) + da2->maback += (da2->rowoffset << 1); + da2->maback &= da2->vram_display_mask; + da2->ma = da2->maback; + } + else + { + da2->sc++; + da2->sc &= 31; + da2->ma = da2->maback; + } + } + //da2->hsync_divisor = !da2->hsync_divisor; + + //disable for 256 color mode + //if (da2->hsync_divisor && (da2->crtc[0x17] & 4)) + // return; + + da2->vc++; + da2->vc &= 2047; + + if (da2->vc == da2->dispend) + { + //if (da2->vblank_start) + // da2->vblank_start(da2); + // da2_log("VC dispend\n"); + da2->dispon = 0; + //if (da2->crtc[10] & 0x20) da2->cursoron = 0; + //else da2->cursoron = da2->blink & 16; + if (da2->ioctl[LS_MODE] & 1) {//in text mode + if (da2->attrregs[LV_CURSOR_CONTROL] & 0x01)//cursor blinking + { + da2->cursoron = (da2->blink | 1) & da2->blinkconf; + } + else + { + da2->cursoron = 0; + } + if (!(da2->blink & (0x10 - 1)))//force redrawing for cursor and blink attribute + da2->fullchange = 2; + } + da2->blink++; + + for (x = 0; x < ((da2->vram_mask + 1) >> 12); x++) + { + if (da2->changedvram[x]) + da2->changedvram[x]--; + } + // memset(changedvram,0,2048); del + if (da2->fullchange) + { + da2->fullchange--; + //da2->fps++; + } + } + if (da2->vc == da2->vsyncstart) + { + int wx, wy; + // da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); + da2->dispon = 0; + da2->cgastat |= 8; + x = da2->hdisp; + + if (da2->interlace && !da2->oddeven) da2->lastline++; + if (da2->interlace && da2->oddeven) da2->firstline--; + + wx = x; + wy = da2->lastline - da2->firstline; + + da2_doblit(da2->firstline_draw, da2->lastline_draw + 1, wx, wy, da2); + + //readflash = 0; + + da2->firstline = 2000; + da2->lastline = 0; + + da2->firstline_draw = 2000; + da2->lastline_draw = 0; + + da2->oddeven ^= 1; + + changeframecount = da2->interlace ? 3 : 2; + da2->vslines = 0; + + //if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch + (da2->rowoffset << 1) + ((da2->crtc[5] & 0x60) >> 5); + //else da2->ma = da2->maback = da2->ma_latch + ((da2->crtc[5] & 0x60) >> 5); + //da2->ca = ((da2->crtc[0xe] << 8) | da2->crtc[0xf]) + ((da2->crtc[0xb] & 0x60) >> 5) + da2->ca_adj; + if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch; + else da2->ma = da2->maback = da2->ma_latch; + da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj; + + da2->ma <<= 1; + da2->maback <<= 1; + da2->ca <<= 1; + + //if (!da2->video_res_override) + //{ + //da2->video_res_x = wx; + //da2->video_res_y = wy + 1; + + if (da2->ioctl[LS_MODE] & 1) /*Text mode*/ + { + //da2->video_res_x /= da2->char_width; + //da2->video_res_y /= (da2->crtc[9] & 31) + 1; + //da2->video_bpp = 0; + } + else + { + //if (da2->crtc[9] & 0x80) + // da2->video_res_y /= 2; + //if (!(da2->crtc[0x17] & 2)) + // da2->video_res_y *= 4; + //else if (!(da2->crtc[0x17] & 1)) + // da2->video_res_y *= 2; + //da2->video_res_y /= (da2->crtc[9] & 31) + 1; + //if (da2->render == da2_render_8bpp_lowres || + // da2->render == da2_render_15bpp_lowres || + // da2->render == da2_render_16bpp_lowres || + // da2->render == da2_render_24bpp_lowres || + // da2->render == da2_render_32bpp_lowres) + //da2->video_res_x /= 2; + + //switch (da2->gdcreg[5] & 0x60) + //{ + //case 0x00: da2->video_bpp = 4; break; + //case 0x20: da2->video_bpp = 2; break; + //case 0x40: case 0x60: da2->video_bpp = da2->bpp; break; + //} + //da2->video_bpp = da2->bpp; + } + //} + //if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma + (da2->rowoffset << 1); + + // da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); + + //if (da2->vsync_callback) + // da2->vsync_callback(da2); + } + if (da2->vc == da2->vtotal) + { + // da2_log("VC vtotal\n"); + + + // printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); + da2->vc = 0; + da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; + da2->dispon = 1; + da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; + da2->scrollcache = da2->attrregs[LV_PANNING] & 7; + //da2->linecountff = 0; + + //da2->hwcursor_on = 0; + //da2->hwcursor_latch = da2->hwcursor; + + //da2->overlay_on = 0; + //da2->overlay_latch = da2->overlay; + // da2_log("Latch HWcursor addr %08X\n", da2_hwcursor_latch.addr); + + // da2_log("ADDR %08X\n",hwcursor_addr); + } + if (da2->sc == (da2->crtc[LC_VERTICAL_SYNC_START] & 31)) + da2->con = 1; + } + // printf("2 %i\n",da2_vsyncstart); + //da2_log("da2_poll %i %i %i %i %i %i %i\n", ins, da2->dispofftime, da2->dispontime, da2->vidtime, cyc_total, da2->linepos, da2->vc); + //da2_log("r"); +} + +static void da2_loadfont(char* fname, void* p) { + da2_t* da2 = (da2_t*)p; + uint8_t buf; + //uint32_t code = 0; + 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 > DA2_FONTROM_SIZE) { + fsize = DA2_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) { + fread(&buf, sizeof(uint8_t), 1, mfile); + da2->mmio.font[j] = buf; + j++; + } + fclose(mfile); + return; +} + +/* 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} +}; + +void da2_reset_ioctl(da2_t* da2) +{ + da2->ioctl[LS_RESET] = 0x00; /* Bit 0: Reset sequencer */ + da2_outw(LS_INDEX, 0x0302, da2); /* Index 02, Bit 1: VGA passthrough, Bit 0: Character Mode */ + da2_outw(LS_INDEX, 0x0008, da2); /* Index 08, Bit 0: Enable MMIO */ +} + +static void +da2_reset(void* priv) +{ + da2_t* da2 = (da2_t*)priv; + + /* Initialize drawing */ + da2->bitblt.exec = DA2_BLT_CIDLE; + da2->render = da2_render_blank; + da2_reset_ioctl(da2); + + da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ + da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ + da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ + da2->ioctl[LS_CONFIG1] = OldLSI | Mon_ID3 | Page_Two; /* Configuration(Low) : DA - 2, Monitor ID 3, 1024 KB */ + da2->ioctl[LS_CONFIG2] = Mon_ID1; /* Configuration (High): Monitor ID 0-2 */ + da2->fctl[0] = 0x2b; /* 3E3h:0 */ + da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ + da2->attrregs[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ + da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ + da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ + da2->ma_latch = 0; + //da2->gdcramlatched = 0; + da2->interlace = 0; + da2->attrregs[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ + da2->attr_palette_enable = 0; /* disable attribute generator */ + + /* Set default color palette (Display driver of Win 3.1 won't reset palette) */ + da2_out(0x3c8, 0, da2); + for (int i = 0; i < 256; i++) { + da2_out(0x3c9, ps55_palette_color[i & 0x3F][0], da2); + da2_out(0x3c9, ps55_palette_color[i & 0x3F][1], da2); + da2_out(0x3c9, ps55_palette_color[i & 0x3F][2], da2); + } +} + +static void *da2_init() +{ + //Todo: init regs, gaiji memory, video memory, I/O handlers, font ROM + + if (svga_get_pri() == NULL) + return NULL; + svga_t *mb_vga = svga_get_pri(); + mb_vga->cable_connected = 0; + + da2_t* da2 = malloc(sizeof(da2_t)); + da2->mb_vga = mb_vga; + + da2->dispontime = 1000ull << 32; + da2->dispofftime = 1000ull << 32; + int memsize = 1024 * 1024; + da2->vram = malloc(memsize); + da2->vram_mask = memsize - 1; + //da2->gram_display_mask = (memsize - 1) >> 3; + da2->cram = malloc(0x1000); + //da2->cram_display_mask = 0x1000 - 1; + da2->vram_display_mask = DA2_MASK_CRAM; + da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h + da2_loadfont(DA2_FONTROM_PATH, da2); + + mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); + da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ +#ifdef ENABLE_DA2_DEBUGBLT + da2->bitblt.debug_reg = malloc(DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE); + da2->mmdbg_fp = fopen("da2_mmiowdat.txt", "w"); + da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); + da2->bitblt.debug_reg_ip = 0; +#endif + da2->bitblt.payload_addr = 0; + da2_reset(da2); + + mem_mapping_add(&da2->mmio.mapping, 0xA0000, 0x20000, da2_mmio_read, da2_mmio_readw, NULL, da2_mmio_write, da2_mmio_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); + //da2_log("DA2mmio new mapping: %X, base: %x, size: %x\n", &da2->mmio.mapping, da2->mmio.mapping.base, da2->mmio.mapping.size); + + mem_mapping_disable(&da2->mmio.mapping); + + mem_mapping_add(&da2->cmapping, 0xE0000, 0x1000, da2_code_readb, da2_code_readw, NULL, da2_code_writeb, da2_code_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); + + mem_mapping_disable(&da2->cmapping); + + timer_add(&da2->timer, da2_poll, da2, 0); + da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ + timer_add(&da2->bitblt.timer, da2_bitblt_exec, da2, 0); + + return da2; +} +static int da2_available() +{ + return rom_present(DA2_FONTROM_PATH); +} + +void da2_close(void *p) +{ + da2_t *da2 = (da2_t *)p; + + /* dump mem for debug */ +#ifndef RELEASE_BUILD + FILE* f; + f = fopen("da2_cram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->cram, 0x1000, 1, f); + fclose(f); + } + f = fopen("da2_vram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->vram, 1024*1024, 1, f); + fclose(f); + } + f = fopen("da2_gram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->mmio.ram, 256*1024, 1, f); + fclose(f); + } + f = fopen("da2_attrpal.dmp", "wb"); + if (f != NULL) { + fwrite(da2->attrregs, 32, 1, f); + fclose(f); + } + f = fopen("da2_dacrgb.dmp", "wb"); + if (f != NULL) { + fwrite(da2->vgapal, 3*256, 1, f); + fclose(f); + } + f = fopen("da2_daregs.txt", "w"); + if (f != NULL) { + for (int i=0;i<0x10;i++) + fprintf(f, "3e1(ioctl) %02X: %4X\n", i, da2->ioctl[i]); + for (int i = 0; i < 0x20; i++) + fprintf(f, "3e3(fctl) %02X: %4X\n", i, da2->fctl[i]); + for (int i = 0; i < 0x20; i++) + fprintf(f, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); + for (int i = 0; i < 0x40; i++) + fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrregs[i]); + for (int i = 0; i < 0x10; i++) + fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); + for (int i = 0; i < 0x10; i++) + fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); + fclose(f); + } +#ifdef ENABLE_DA2_DEBUGBLT + f = fopen("da2_bltdump.csv", "w"); + if (f != NULL && da2->bitblt.debug_reg_ip > 0) { + /* print header */ + for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { + if (da2->bitblt.debug_reg[(da2->bitblt.debug_reg_ip - 1) * DA2_DEBUG_BLTLOG_SIZE + y] != DA2_DEBUG_BLT_NEVERUSED) + fprintf(f, "\"%02X\"\t", y); + } + fprintf(f, "\n"); + /* print data */ + for (int x = 0; x < da2->bitblt.debug_reg_ip; x++) { + for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { + if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_NEVERUSED) + ; + else if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_USEDRESET) + fprintf(f, "\"\"\t"); + else + fprintf(f, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]); + } + fprintf(f, "\n"); + } + fclose(f); + } + if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); + if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); + free(da2->bitblt.debug_reg); +#endif +#endif + free(da2->cram); + free(da2->vram); + free(da2->changedvram); + free(da2); +} + +void da2_speed_changed(void *p) +{ + da2_t* da2 = (da2_t*)p; + da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); + da2_recalctimings(da2); +} + +void da2_force_redraw(void *p) +{ + da2_t* da2 = (da2_t*)p; + + da2->fullchange = changeframecount; +} + +//void da2_add_status_info(char *s, int max_len, void *p) +//{ +// da2_t* da2 = (da2_t*)p; +// char temps[128]; +// if (!(da2->pos_regs[2] & 0x01)) strcpy(temps, "Render: DA2 disabled\n"); +// else if (da2->render == da2_render_blank) strcpy(temps, "Render: DA2 blank\n"); +// else if (da2->render == da2_render_text) strcpy(temps, "Render: DA2 text (mode 8 or E)\n"); +// else if (da2->render == da2_render_textm3) strcpy(temps, "Render: DA2 EGA compatible text (mode 3)\n"); +// else if (da2->render == da2_render_color_4bpp) strcpy(temps, "Render: DA2 4 bpp graphics (mode A or D)\n"); +// else if (da2->render == da2_render_color_8bpp) strcpy(temps, "Render: DA2 8 bpp graphics (mode F)\n"); +// else strcpy(temps, "Render: DA2 unknown render\n"); +// strncat(s, temps, max_len); +// +// sprintf(temps, "Resolution : %i x %i\n", da2->video_res_x, da2->video_res_y); +// strncat(s, temps, max_len); +// +// sprintf(temps, "Refresh rate : %i Hz\n", da2->frames); +// da2->frames = 0; +// strncat(s, temps, max_len); +// +// sprintf(temps, "Render lines : %i\n\n", da2->writelines); +// da2->writelines = 0; +// strncat(s, temps, max_len); +//} + +const device_t ps55da2_device = { + .name = "IBM Display Adapter II (MCA)", + .internal_name = "ps55da2", + .flags = DEVICE_MCA, + .local = 0, + .init = da2_init, + .close = da2_close, + .reset = da2_reset, + { .available = da2_available }, + .speed_changed = da2_speed_changed, + .force_redraw = da2_force_redraw, + .config = NULL +}; + +void +da2_device_add(void) +{ + if (!da2_standalone_enabled) + return; + + if (machine_has_bus(machine, MACHINE_BUS_MCA)) + device_add(&ps55da2_device); + else + return; +} diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 93c1eb669..6d952ddb7 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -431,10 +431,24 @@ svga_in(uint16_t addr, void *priv) ret = svga->attrregs[svga->attraddr]; break; case 0x3c2: - if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) - ret = 0; + if (svga->cable_connected) + { + if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) + ret = 0; + else + ret = 0x10; + } else - ret = 0x10; + { + // The Display Adapter has own Monitor Type Detection bit in the different I/O port (I/O 3E0h, 3E1h). + // When the monitor cable is connected to the Display Adapter, this port returns the value as no cable connection. + // The Power-on Self Test of PS/55 tries detecting the monitor on the planar VGA. + // If it fails, then the POST reads the NVRAM set by the reference diskette, and sets the BIOS Data Area (Mem 487h, 489h). + if (svga->vgapal[0].r >= 10 || svga->vgapal[0].g >= 10 || svga->vgapal[0].b >= 10) + ret = 0; + else + ret = 0x10; + } break; case 0x3c3: ret = vga_on; @@ -1359,6 +1373,8 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 32; svga->translate_address = NULL; + + svga->cable_connected = 1; svga->ksc5601_english_font_type = 0; vga_on = 1; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index b6e1bd2f9..cda3f95e0 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -367,6 +367,8 @@ video_post_reset(void) if (xga_standalone_enabled) xga_device_add(); + if (da2_standalone_enabled) + da2_device_add(); /* Reset the graphics card (or do nothing if it was already done by the machine's init function). */ video_reset(gfxcard[0]); diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 8b2e761a3..699cfe85e 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -103,6 +103,39 @@ vga_in(uint16_t addr, void *priv) return temp; } +void vga_disable(void* p) +{ + vga_t* vga = (vga_t*)p; + svga_t* svga = &vga->svga; + + pclog("vga_disable %04X:%04X\n", cs >> 4, cpu_state.pc); + io_removehandler(0x03a0, 0x0040, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + mem_mapping_disable(&svga->mapping); + svga->vga_enabled = 0; +} + +void vga_enable(void* p) +{ + vga_t* vga = (vga_t*)p; + svga_t* svga = &vga->svga; + + pclog("vga_enable %04X:%04X\n", cs >> 4, cpu_state.pc); + io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + if (!(svga->miscout & 1)) + io_sethandler(0x03a0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + + mem_mapping_enable(&svga->mapping); + svga->vga_enabled = 1; +} + +int vga_isenabled(void* p) +{ + vga_t* vga = (vga_t*)p; + svga_t* svga = &vga->svga; + + return svga->vga_enabled; +} + static void * vga_init(const device_t *info) { @@ -149,6 +182,7 @@ ps1vga_init(const device_t *info) vga->svga.bpp = 8; vga->svga.miscout = 1; + vga->svga.vga_enabled = 1; return vga; } From 7c5e82b2abf58ea514998113976beb8404604f53 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:44:11 +0900 Subject: [PATCH 05/82] Added PS/55 fdc emulation, fixed a bug in MT read --- src/floppy/fdc.c | 110 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 8 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 3fd492bd2..a878853e4 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -734,6 +734,20 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) drive = real_drive(fdc, fdc->dor & 3); fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); } + /* FIFO test mode (PS/55 only? This is not documented in neither the PS/2 HITR nor the 82077AA datasheet.) + The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h. + If it fails, then floppy drives will be treated as DD drives. */ + if (fdc->flags & FDC_FLAG_PS55) { + if (val & 0x04) + { + fdc->tfifo = 8; + fdc->fifointest = 1; + } + else { + fdc->tfifo = 1; + fdc->fifointest = 0; + } + } return; case 4: if (!(fdc->flags & FDC_FLAG_NO_DSR_RESET)) { @@ -761,6 +775,14 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->dsr = val; return; case 5: /*Command register*/ + if (fdc->fifointest) + { + pclog("FIFO buffer position = %X\n", ((fifo_t *)fdc->fifo_p)->end); + fifo_write(val, fdc->fifo_p); + if (fifo_get_full(fdc->fifo_p)) + fdc->stat &= ~0x80; + break; + } if ((fdc->stat & 0xf0) == 0xb0) { if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) { fdc->dat = val; @@ -1249,7 +1271,27 @@ fdc_read(uint16_t addr, void *priv) ret |= 0x40; if (fdc->fintr || fdc->reset_stat) /* INTR */ ret |= 0x80; - } else + } + else if (fdc->flags & FDC_FLAG_PS55) { + /* Status Register A (PS/2, PS/55) */ + /* | INT PEND | nDRV2 | STEP | nTRK0 | HDSEL | nIDX | nWP | DIR | */ + ret = 0x04; + if (!fdc->seek_dir) /* DIRECTION */ + ret |= 0x01; + if (!writeprot[drive]) /* nWRITEPROT */ + ret |= 0x02; + if (fdd_get_head(drive)) /* HDSEL */ + ret |= 0x08; + if (!fdd_track0(drive)) /* nTRK0 */ + ret |= 0x10; + if (fdc->step) /* STEP */ + ret |= 0x20; + if (!fdd_get_type(1)) /* -Drive 2 Installed */ + ret |= 0x40; + if (fdc->fintr || fdc->reset_stat) /* INTR */ + ret |= 0x80; + } + else ret = 0xff; break; case 1: /* STB */ @@ -1277,7 +1319,19 @@ fdc_read(uint16_t addr, void *priv) default: break; } - } else { + } + else if (fdc->flags & FDC_FLAG_PS55) { + /* Status Register B (PS/2, PS/55) */ + /* | 1 | 1 | DS0 | WD TOGGLE | RD TOGGLE | WE | MOT EN1 | MOT EN0 | */ + ret = 0xc0; + if (motoron[0]) /* Bit 0: MOT EN0 */ + ret |= 1; + if (motoron[1]) /* Bit 1: MOT EN1 */ + ret |= 2; + if(real_drive(fdc, fdc->dor & 3) == 0) /* Bit 5: Drive Select 0 */ + ret |= 0x20; + } + else { if (is486 || !fdc->enable_3f1) ret = 0xff; else { @@ -1326,7 +1380,12 @@ fdc_read(uint16_t addr, void *priv) ret = 0x10; else ret = 0x00; - } else if (!fdc->enh_mode) + } + else if (fdc->flags & FDC_FLAG_PS55) { + /* error when ret = 1, 2*/ + ret = (fdc->fifointest) ? 4 : 0; + } + else if (!fdc->enh_mode) ret = 0x20; else ret = fdc->rwc[drive] << 4; @@ -1335,6 +1394,11 @@ fdc_read(uint16_t addr, void *priv) ret = fdc->stat; break; case 5: /*Data*/ + if (fdc->fifointest) + { + ret = fifo_read(fdc->fifo_p); + break; + } if ((fdc->stat & 0xf0) == 0xf0) { fdc->stat &= ~0x80; if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->fifo) { @@ -1377,7 +1441,18 @@ fdc_read(uint16_t addr, void *priv) ret |= (fdc->rate & 0x03); } else ret = 0x00; - } else { + } + else if (fdc->flags & FDC_FLAG_PS55) { + /* Digital Input Register (PS/2, PS/55) */ + /* | DSKCHG | 1 | 1 | 1 | 1 | DRATE1 | DRATE0 | nHDEN | */ + ret = 0x78; + ret |= (fdc->rate & 0x03) << 1; + if (fdc->rate == 1 || fdc->rate == 2) + ret |= 0x01; + if (fdc->dor & (0x10 << drive)) + ret |= (fdd_changed[drive] || drive_empty[drive]) ? 0x80 : 0x00; + } + else { if (fdc->dor & (0x10 << drive)) { if ((drive == 1) && (fdc->flags & FDC_FLAG_TOSHIBA)) ret = 0x00; @@ -1409,7 +1484,7 @@ static void fdc_poll_common_finish(fdc_t *fdc, int compare, int st5) { fdc_int(fdc, 1); - if (!(fdc->flags & FDC_FLAG_PS1)) + if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55))) fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; @@ -1635,6 +1710,8 @@ fdc_callback(void *priv) return; } if (fdd_get_head(real_drive(fdc, fdc->drive)) == 0) { + fdc->sector = 1; + fdc->head |= 1; fdd_set_head(real_drive(fdc, fdc->drive), 1); if (!fdd_is_double_sided(real_drive(fdc, fdc->drive))) { fdc_noidam(fdc); @@ -1646,6 +1723,7 @@ fdc_callback(void *priv) else if (fdc->params[5] == 0) fdc->sector++; ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); + //fdc_log("cb_rwsect: %d %d %d %d %d %xh\n", real_drive(fdc, fdc->drive), fdc->sector, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); switch (fdc->interrupt) { case 5: case 9: @@ -1708,7 +1786,7 @@ fdc_callback(void *priv) } else { fdc->interrupt = -2; fdc_int(fdc, 1); - if (!(fdc->flags & FDC_FLAG_PS1)) + if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55))) fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->drive; @@ -1800,7 +1878,7 @@ fdc_error(fdc_t *fdc, int st5, int st6) timer_disable(&fdc->timer); fdc_int(fdc, 1); - if (!(fdc->flags & FDC_FLAG_PS1)) + if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55))) fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = 0x40 | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; @@ -1964,6 +2042,7 @@ fdc_noidam(fdc_t *fdc) void fdc_nosector(fdc_t *fdc) { + pclog("nosector error\n"); fdc_error(fdc, 4, 0); } @@ -2209,7 +2288,7 @@ fdc_reset(void *priv) fdc->enable_3f1 = 1; fdc_update_enh_mode(fdc, 0); - if (fdc->flags & FDC_FLAG_PS1) + if (fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55)) fdc_update_densel_polarity(fdc, 0); else fdc_update_densel_polarity(fdc, 1); @@ -2230,6 +2309,7 @@ fdc_reset(void *priv) fdc->fifo = 0; fdc->tfifo = 1; + fdc->fifointest = 0; if (fdc->flags & FDC_FLAG_PCJR) { fdc->dma = 0; @@ -2551,6 +2631,20 @@ const device_t fdc_at_ps1_2121_device = { .config = NULL }; +const device_t fdc_at_ps55_device = { + .name = "PC/AT Floppy Drive Controller (PS/55)", + .internal_name = "fdc_at_ps55", + .flags = 0, + .local = FDC_FLAG_AT | FDC_FLAG_PS55, + .init = fdc_init, + .close = fdc_close, + .reset = fdc_reset, + {.available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t fdc_at_smc_device = { .name = "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)", .internal_name = "fdc_at_smc", From 4b5943dd7d05cc060245af0889e7a3e8b7ffebb9 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:46:15 +0900 Subject: [PATCH 06/82] Added a display configuration for IBM DA2 --- src/qt/qt_settingsdisplay.cpp | 6 ++++++ src/qt/qt_settingsdisplay.ui | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index db8c30e5d..42617c4be 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -25,6 +25,7 @@ extern "C" { #include <86box/machine.h> #include <86box/video.h> #include <86box/vid_xga_device.h> +#include <86box/vid_ps55da2.h> } #include "qt_deviceconfig.hpp" @@ -56,6 +57,7 @@ SettingsDisplay::save() voodoo_enabled = ui->checkBoxVoodoo->isChecked() ? 1 : 0; ibm8514_standalone_enabled = ui->checkBox8514->isChecked() ? 1 : 0; xga_standalone_enabled = ui->checkBoxXga->isChecked() ? 1 : 0; + da2_standalone_enabled = ui->checkBoxDa2->isChecked() ? 1 : 0; } void @@ -162,6 +164,7 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) bool machineSupports8514 = ((machineHasIsa16 || machineHasMca) && !videoCardHas8514); bool machineSupportsXga = (((machineHasIsa16 && device_available(&xga_isa_device)) || (machineHasMca && device_available(&xga_device))) && !videoCardHasXga); + bool machineSupportsDa2 = machineHasMca && device_available(&ps55da2_device); ui->checkBox8514->setEnabled(machineSupports8514); ui->checkBox8514->setChecked(ibm8514_standalone_enabled && machineSupports8514); @@ -169,6 +172,9 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) ui->checkBoxXga->setEnabled(machineSupportsXga); ui->checkBoxXga->setChecked(xga_standalone_enabled && machineSupportsXga); + ui->checkBoxDa2->setEnabled(machineSupportsDa2); + ui->checkBoxDa2->setChecked(da2_standalone_enabled && machineSupportsDa2); + ui->pushButtonConfigureXga->setEnabled(ui->checkBoxXga->isEnabled() && ui->checkBoxXga->isChecked()); int c = 2; diff --git a/src/qt/qt_settingsdisplay.ui b/src/qt/qt_settingsdisplay.ui index a9b7e6e2c..e3e081848 100644 --- a/src/qt/qt_settingsdisplay.ui +++ b/src/qt/qt_settingsdisplay.ui @@ -113,6 +113,13 @@ + + + + IBM PS/55 Display Adapter Graphics + + + @@ -133,7 +140,7 @@ - + Qt::Vertical From 44ce0dc2827216f2f240970ed642ba09722b330c Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:52:16 +0900 Subject: [PATCH 07/82] Added DA2 config, Changed ca keys for PS/55 --- src/86box.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/86box.c b/src/86box.c index 5e1f58413..82eedbd78 100644 --- a/src/86box.c +++ b/src/86box.c @@ -186,6 +186,7 @@ int voodoo_enabled = 0; /* (C) video o int lba_enhancer_enabled = 0; /* (C) enable Vision Systems LBA Enhancer */ int ibm8514_standalone_enabled = 0; /* (C) video option */ int xga_standalone_enabled = 0; /* (C) video option */ +int da2_standalone_enabled = 0; /* (C) video option */ uint32_t mem_size = 0; /* (C) memory size (Installed on system board)*/ uint32_t isa_mem_size = 0; /* (C) memory size (ISA Memory Cards) */ @@ -1061,12 +1062,13 @@ pc_init_modules(void) void pc_send_ca(uint16_t sc) { + /* Use R-Alt because 5576-002 keyboard assigns L-Alt as */ keyboard_input(1, 0x1D); /* Ctrl key pressed */ - keyboard_input(1, 0x38); /* Alt key pressed */ + keyboard_input(1, 0x138); /* R-Alt key pressed */ keyboard_input(1, sc); usleep(50000); keyboard_input(0, sc); - keyboard_input(0, 0x38); /* Alt key released */ + keyboard_input(0, 0x138); /* R-Alt key released */ keyboard_input(0, 0x1D); /* Ctrl key released */ } From a241a3ae8fdcbe716fd27d3a83b29fbdb8b1ee68 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:54:08 +0900 Subject: [PATCH 08/82] added/updated headers --- src/include/86box/86box.h | 1 + src/include/86box/fdc.h | 4 +++- src/include/86box/hdc.h | 1 + src/include/86box/machine.h | 1 + src/include/86box/mca.h | 1 + src/include/86box/vid_ps55da2.h | 24 ++++++++++++++++++++++++ src/include/86box/vid_svga.h | 5 +++++ src/include/86box/vid_vga.h | 4 ++++ src/include/86box/video.h | 3 +++ 9 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/include/86box/vid_ps55da2.h diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index c91b8d406..d21bba49c 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -137,6 +137,7 @@ extern int sound_is_float; /* (C) sound uses FP values */ extern int voodoo_enabled; /* (C) video option */ extern int ibm8514_standalone_enabled; /* (C) video option */ extern int xga_standalone_enabled; /* (C) video option */ +extern int da2_standalone_enabled; /* (C) video option */ extern uint32_t mem_size; /* (C) memory size (Installed on system board) */ extern uint32_t isa_mem_size; /* (C) memory size (ISA Memory Cards) */ extern int cpu; /* (C) cpu type */ diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index ef78239cd..0d71dd374 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -52,6 +52,7 @@ #define FDC_FLAG_ALI 0x800 /* ALi M512x / M1543C */ #define FDC_FLAG_NO_DSR_RESET 0x1000 /* Has no DSR reset */ #define FDC_FLAG_NEC 0x2000 /* Is NEC upd765-compatible */ +#define FDC_FLAG_PS55 0x4000 /* PS/55 */ #define FDC_FLAG_SEC 0x10000 /* Is Secondary */ #define FDC_FLAG_TER 0x20000 /* Is Tertiary */ #define FDC_FLAG_QUA 0x40000 /* Is Quaternary */ @@ -100,7 +101,6 @@ typedef struct fdc_t { uint8_t densel_force; uint8_t fifo; uint8_t tfifo; - uint8_t fifobufpos; uint8_t drv2en; uint8_t gap; @@ -145,6 +145,7 @@ typedef struct fdc_t { int drvrate[4]; void *fifo_p; + int fifointest; sector_id_t read_track_sector; sector_id_t format_sector_id; @@ -252,6 +253,7 @@ extern const device_t fdc_at_qua_device; extern const device_t fdc_at_actlow_device; extern const device_t fdc_at_ps1_device; extern const device_t fdc_at_ps1_2121_device; +extern const device_t fdc_at_ps55_device; extern const device_t fdc_at_smc_device; extern const device_t fdc_at_ali_device; extern const device_t fdc_at_winbond_device; diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 48235bb1e..734cdf37a 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -53,6 +53,7 @@ extern const device_t st506_xt_toshiba_t1200_device; /* st506_xt_toshiba_t1 extern const device_t esdi_at_wd1007vse1_device; /* esdi_at */ extern const device_t esdi_ps2_device; /* esdi_mca */ +extern const device_t esdi_integrated_device; /* esdi_mca */ extern const device_t ide_isa_device; /* isa_ide */ extern const device_t ide_isa_2ch_device; /* isa_ide_2ch */ diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 8afd5e28f..fe867a4dc 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -887,6 +887,7 @@ extern int machine_ps2_model_70_type3_init(const machine_t *); extern int machine_ps2_model_80_init(const machine_t *); extern int machine_ps2_model_80_axx_init(const machine_t *); extern int machine_ps2_model_70_type4_init(const machine_t *); +extern int machine_ps55_model_50t_init(const machine_t*); /* m_tandy.c */ extern int tandy1k_eeprom_read(void); diff --git a/src/include/86box/mca.h b/src/include/86box/mca.h index e048a6131..2d31fe33d 100644 --- a/src/include/86box/mca.h +++ b/src/include/86box/mca.h @@ -3,6 +3,7 @@ extern void mca_init(int nr_cards); extern void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), uint8_t (*feedb)(void *priv), void (*reset)(void *priv), void *priv); +extern void mca_add_to_slot(uint8_t(*read)(int addr, void* priv), void (*write)(int addr, uint8_t val, void* priv), uint8_t(*feedb)(void* priv), void (*reset)(void* priv), void* priv, int c); extern void mca_set_index(int index); extern uint8_t mca_read(uint16_t port); extern uint8_t mca_read_index(uint16_t port, int index); diff --git a/src/include/86box/vid_ps55da2.h b/src/include/86box/vid_ps55da2.h new file mode 100644 index 000000000..70007be19 --- /dev/null +++ b/src/include/86box/vid_ps55da2.h @@ -0,0 +1,24 @@ +/* + * 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. + * + * IBM PS/55 Display Adapter II emulation. + * + * + * + * Authors: Akamaki. + * + * Copyright 2024 Akamaki. + */ + +#ifndef VIDEO_DA2_DEVICE_H +#define VIDEO_DA2_DEVICE_H + +#ifdef EMU_DEVICE_H +extern const device_t ps55da2_device; +#endif +#endif /*VIDEO_DA2_DEVICE_H*/ diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 3d68c1a34..72b755cf1 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -216,6 +216,11 @@ typedef struct svga_t { int override; void *priv; + int vga_enabled; + /* The PS/55 POST BIOS has a special monitor detection for its internal VGA + when the monitor is connected to the Display Adapter. */ + int cable_connected; + uint8_t crtc[256]; uint8_t gdcreg[256]; uint8_t attrregs[32]; diff --git a/src/include/86box/vid_vga.h b/src/include/86box/vid_vga.h index bc552b285..62cee8e9f 100644 --- a/src/include/86box/vid_vga.h +++ b/src/include/86box/vid_vga.h @@ -33,4 +33,8 @@ static video_timings_t timing_vga = { VIDEO_ISA, 8, 16, 32, 8, 16, 32 }; void vga_out(uint16_t addr, uint8_t val, void *priv); uint8_t vga_in(uint16_t addr, void *priv); +void vga_disable(void* p); +void vga_enable(void* p); +int vga_isenabled(void* p); + #endif /*VIDEO_VGA_H*/ diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 9cbd0399f..3db41d2ab 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -313,6 +313,9 @@ extern const device_t mach32_mca_device; extern const device_t mach32_pci_device; extern const device_t mach32_onboard_pci_device; +/* IBM Display Adapter (PS/55) */ +extern void da2_device_add(void); + /* ATi Mach64 */ extern const device_t mach64gx_isa_device; extern const device_t mach64gx_vlb_device; From 84f49c355344eece68892faffe8c57e5816864a0 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 15 Aug 2024 23:30:16 +0900 Subject: [PATCH 09/82] Fixed text cursor size changing --- src/video/vid_ps55da2.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 13f823c83..0378cbc3c 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1568,7 +1568,6 @@ static void da2_render_text(da2_t* da2) } //Draw character for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank - //draw -= 13; // SBCS or DBCS left half if (chr_wide == 0) { if (attr & 0x01) chr_wide = 1; @@ -1742,7 +1741,7 @@ static void da2_render_textm3(da2_t* da2) // fg = 0; //} for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[fg]];//under line (white) + p[n] = da2->pallook[da2->egapal[fg]]; } da2->ma += 2; p += 13; @@ -2684,7 +2683,7 @@ void da2_poll(void* priv) da2->hdisp_on = 0; da2->linepos = 0; - if (da2->sc == (da2->crtc[LC_VERTICAL_SYNC_END] & 31)) + if (da2->sc == (da2->crtc[LC_CURSOR_ROW_END] & 31)) da2->con = 0; if (da2->dispon) { @@ -2854,7 +2853,7 @@ void da2_poll(void* priv) // da2_log("ADDR %08X\n",hwcursor_addr); } - if (da2->sc == (da2->crtc[LC_VERTICAL_SYNC_START] & 31)) + if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) da2->con = 1; } // printf("2 %i\n",da2_vsyncstart); From 935c8b6ed893e08f52a69e55a99f0fed719aede7 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:04:42 +0900 Subject: [PATCH 10/82] cleanup code --- src/video/vid_ps55da2.c | 192 +++------------------------------------- 1 file changed, 12 insertions(+), 180 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 0378cbc3c..c5e64694d 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -259,14 +259,12 @@ typedef struct da2_t int crtcaddr; uint8_t miscout; - //int vidclock; uint32_t decode_mask; uint32_t vram_max; uint32_t vram_mask; uint32_t gdcla[8]; - //int gdcramlatched; uint32_t gdcinput[8]; uint32_t gdcsrc[8]; uint32_t debug_vramold[8]; @@ -275,7 +273,6 @@ typedef struct da2_t int dac_read, dac_write, dac_pos; int dac_r, dac_g; - //IO 3DAh Input Status Register 2 uint8_t cgastat; uint8_t plane_mask; @@ -336,24 +333,11 @@ typedef struct da2_t int fullchange; - //int video_res_x, video_res_y, video_bpp; - //int video_res_override; /*If clear then SVGA code will set above variables, if - // set then card code will*/ - //int frames, writelines; - void (*render)(struct da2_t* da2); - //void (*recalctimings_ex)(struct da2_t* da2); - - //void (*video_out)(uint16_t addr, uint8_t val, void* p); - //uint8_t(*video_in) (uint16_t addr, void* p); /*If set then another device is driving the monitor output and the SVGA card should not attempt to display anything */ - int override; - //void* p; - - /*Used to implement CRTC[0x17] bit 2 hsync divisor*/ - //int hsync_divisor; + int override; /* end VGA compatible regs*/ struct @@ -852,7 +836,6 @@ void da2_out(uint16_t addr, uint16_t val, void *p) break; case 0x3C9: /* Data */ //da2_log("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI); - //da2_log("DS %X\n",DS); da2->dac_status = 0; da2->fullchange = changeframecount; switch (da2->dac_pos) @@ -887,10 +870,9 @@ void da2_out(uint16_t addr, uint16_t val, void *p) //if (da2->ioctl[da2->ioctladdr & 15] != val) // da2_log("ioctl changed %x: %x -> %x %04X:%04X\n", da2->ioctladdr & 15, da2->ioctl[da2->ioctladdr & 15], val, cs >> 4, cpu_state.pc); oldval = da2->ioctl[da2->ioctladdr]; - //if (da2->ioctladdr == 0x3) return;//monitor color da2->ioctl[da2->ioctladdr] = val; if (oldval != val) { - if (da2->ioctladdr == LS_RESET && val & 0x01) /* Mode register */ + if (da2->ioctladdr == LS_RESET && val & 0x01) /* Reset register */ da2_reset_ioctl(da2); else if (da2->ioctladdr == LS_MODE && ((oldval ^ val) & 0x03)) /* Mode register */ { @@ -1077,10 +1059,8 @@ void da2_out(uint16_t addr, uint16_t val, void *p) uint16_t da2_in(uint16_t addr, void *p) { da2_t * da2 = (da2_t *)p; - //svga_t *svga = &da2->svga; uint16_t temp; -// if (addr != 0x3da) da2_log("IN gd5429 %04X\n", addr); switch (addr) { case 0x3c3: @@ -1119,19 +1099,6 @@ uint16_t da2_in(uint16_t addr, void *p) if (da2->ioctladdr > 0xf) return 0xff; temp = da2->ioctl[da2->ioctladdr]; if (da2->ioctladdr == LS_STATUS) { /* Status register */ - //da2_log("Read 3E1 DAC status: %d, %d, %d\n", da2->vgapal[0].r, da2->vgapal[0].g, da2->vgapal[0].b); - //da2_log("attr palette: "); - //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->attrregs[i]); - //da2_log("\n"); - //da2_log("vram A0000h: "); - //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->vram[i]); - //da2_log("\n"); - //da2_log("vram B8000h: "); - //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->vram[0x18000 + i]); - //da2_log("\n"); - //da2_log("vram E0000h: "); - //for (int i = 0; i < 16; i++) da2_log("%02x ", da2->cram[i]); - //da2_log("\n"); if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 0x50 && da2->attrregs[LV_COMPATIBILITY] & 0x08) temp &= 0x7F; /* Inactive when the RGB output voltage is high(or the cable is not connected to the color monitor). */ else @@ -1872,7 +1839,6 @@ void da2_updatevidselector(da2_t* da2) { } } - void da2_recalctimings(da2_t* da2) { double crtcconst; @@ -1921,24 +1887,11 @@ void da2_recalctimings(da2_t* da2) //if (da2->attr_palette_enable && (da2->attrregs[0x1f] & 0x08)) if (da2->attrregs[LV_COMPATIBILITY] & 0x08) { - //if (da2->ioctl[0] & 0x01)//256 color mode - //{ - // da2_log("Set videomode to PS/55 8 bpp graphics.\n"); - // da2->vram_display_mask = 0x1ffff; - // da2->render = da2_render_color_8bpp; - //} - //else if (!(da2->ioctl[LS_MODE] & 0x01)) {//16 color graphics mode da2->hdisp *= 16; da2->char_width = 13; da2->hdisp_old = da2->hdisp; - //if (da2->plane_mask == 0x01) {//PS/55 monochrome - // da2_log("Set videomode to PS/55 Monochrome graphics.\n"); - // //da2->render = da2_render_mono; - // da2->render = da2_render_color_4bpp; - // da2->vram_display_mask = 0x1ffff; - //} - if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) {//PS/55 256 color + if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) { da2_log("Set videomode to PS/55 8 bpp graphics.\n"); da2->render = da2_render_color_8bpp; da2->vram_display_mask = DA2_MASK_GRAM; @@ -1950,7 +1903,7 @@ void da2_recalctimings(da2_t* da2) } } else {//text mode - if (da2->attrregs[LV_ATTRIBUTE_CNTL] & 1) {//PS/55 Mode 03 + if (da2->attrregs[LV_ATTRIBUTE_CNTL] & 1) { da2_log("Set videomode to PS/55 Mode 03 text.\n"); da2->render = da2_render_textm3; da2->vram_display_mask = DA2_MASK_CRAM; @@ -1976,7 +1929,6 @@ void da2_recalctimings(da2_t* da2) // da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); - /*da2->char_width = 13;*///PS55TEXT = 13, GFX = 16 //if (da2->recalctimings_ex) // da2->recalctimings_ex(da2); @@ -2174,12 +2126,8 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) else if (!(da2->ioctl[LS_MODE] & 1))//8 or 256 color mode { cycles -= video_timing_read_b; - //readmode 1 - //da2_log("da2_rp: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->readplane, addr); for (int i = 0; i < 8; i++) da2->gdcla[i] = da2->vram[(addr << 3) | i];//read in byte - //da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read in word - //da2->gdcramlatched = 1; //da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 uint8_t ret = 0; @@ -2212,7 +2160,7 @@ static uint16_t da2_mmio_readw(uint32_t addr, void* p) addr &= DA2_MASK_MMIO; for (int i = 0; i < 8; i++) da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read vram into latch - //da2->gdcramlatched = 1; + ////debug //if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) //{ @@ -2320,16 +2268,9 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) da2->changedvram[addr >> 12] = changeframecount; addr <<= 3; - //if (GCLATCHCOND) { - //if (da2->writemode == 2) { - for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch - //} - //else { - // for (int i = 0; i < 8; i++) - // da2->gdcsrc[i] = da2->vram[addr | i];//read in byte from vram - //} - //da2->gdcramlatched = 0; + for (int i = 0; i < 8; i++) + da2->gdcsrc[i] = da2->gdcla[i];//use latch + //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); @@ -2346,7 +2287,6 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) switch (da2->writemode) { case 2: - //case 1: for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) da2->vram[addr | i] = da2->gdcsrc[i]; break; @@ -2372,7 +2312,6 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) //// da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); } break; - //case 2: case 1: if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { @@ -2445,17 +2384,8 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) da2->changedvram[(addr + 1) >> 12] = changeframecount; addr <<= 3; - //if (((da2->gdcreg[LG_COMMAND] & 0x03) || da2->writemode == 2) && da2->writemode != 1) { - //if (GCLATCHCOND) { - //if (da2->writemode == 2) { - for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch - //} - //else { - // for (int i = 0; i < 8; i++) - // da2->gdcsrc[i] = (uint16_t)(da2->vram[addr | i]) | ((uint16_t)(da2->vram[(addr + 8) | i]) << 8);//read in word - //} - //da2->gdcramlatched = 0; + for (int i = 0; i < 8; i++) + da2->gdcsrc[i] = da2->gdcla[i];//use latch if (!(da2->gdcreg[LG_COMMAND] & 0x08)) { @@ -2468,10 +2398,9 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) } //da2_log("da2_Ww m%02x r%02x %05x:%04x=%02x%02x%02x%02x,%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); - switch (da2->writemode)// writemode 0 or 2 rop(0b) 0 or 3 + switch (da2->writemode) { case 2: - //case 1: for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) { @@ -2479,8 +2408,6 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; } break; - //case 2:win - case 0: if (da2->gdcreg[LG_DATA_ROTATION] & 15) val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work @@ -2498,14 +2425,10 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) for (int i = 0; i < 8; i++) if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; else da2->gdcinput[i] = val; - - //for (int i = 0; i < 8; i++)//draft20240722 0211 - // da2->gdcla[i] = 0;//read in word da2_gdcropW(addr, bitmask, da2); // da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); } break; - //case 2: case 1: if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { @@ -2649,7 +2572,6 @@ void da2_poll(void* priv) video_wait_for_buffer(); } - //RENDER if (!da2->override) da2->render(da2); @@ -2705,20 +2627,12 @@ void da2_poll(void* priv) da2->ma = da2->maback; } } - //da2->hsync_divisor = !da2->hsync_divisor; - - //disable for 256 color mode - //if (da2->hsync_divisor && (da2->crtc[0x17] & 4)) - // return; da2->vc++; da2->vc &= 2047; if (da2->vc == da2->dispend) { - //if (da2->vblank_start) - // da2->vblank_start(da2); - // da2_log("VC dispend\n"); da2->dispon = 0; //if (da2->crtc[10] & 0x20) da2->cursoron = 0; //else da2->cursoron = da2->blink & 16; @@ -2745,7 +2659,6 @@ void da2_poll(void* priv) if (da2->fullchange) { da2->fullchange--; - //da2->fps++; } } if (da2->vc == da2->vsyncstart) @@ -2764,8 +2677,6 @@ void da2_poll(void* priv) da2_doblit(da2->firstline_draw, da2->lastline_draw + 1, wx, wy, da2); - //readflash = 0; - da2->firstline = 2000; da2->lastline = 0; @@ -2788,48 +2699,7 @@ void da2_poll(void* priv) da2->maback <<= 1; da2->ca <<= 1; - //if (!da2->video_res_override) - //{ - //da2->video_res_x = wx; - //da2->video_res_y = wy + 1; - - if (da2->ioctl[LS_MODE] & 1) /*Text mode*/ - { - //da2->video_res_x /= da2->char_width; - //da2->video_res_y /= (da2->crtc[9] & 31) + 1; - //da2->video_bpp = 0; - } - else - { - //if (da2->crtc[9] & 0x80) - // da2->video_res_y /= 2; - //if (!(da2->crtc[0x17] & 2)) - // da2->video_res_y *= 4; - //else if (!(da2->crtc[0x17] & 1)) - // da2->video_res_y *= 2; - //da2->video_res_y /= (da2->crtc[9] & 31) + 1; - //if (da2->render == da2_render_8bpp_lowres || - // da2->render == da2_render_15bpp_lowres || - // da2->render == da2_render_16bpp_lowres || - // da2->render == da2_render_24bpp_lowres || - // da2->render == da2_render_32bpp_lowres) - //da2->video_res_x /= 2; - - //switch (da2->gdcreg[5] & 0x60) - //{ - //case 0x00: da2->video_bpp = 4; break; - //case 0x20: da2->video_bpp = 2; break; - //case 0x40: case 0x60: da2->video_bpp = da2->bpp; break; - //} - //da2->video_bpp = da2->bpp; - } - //} - //if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma + (da2->rowoffset << 1); - // da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); - - //if (da2->vsync_callback) - // da2->vsync_callback(da2); } if (da2->vc == da2->vtotal) { @@ -2842,16 +2712,6 @@ void da2_poll(void* priv) da2->dispon = 1; da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; da2->scrollcache = da2->attrregs[LV_PANNING] & 7; - //da2->linecountff = 0; - - //da2->hwcursor_on = 0; - //da2->hwcursor_latch = da2->hwcursor; - - //da2->overlay_on = 0; - //da2->overlay_latch = da2->overlay; - // da2_log("Latch HWcursor addr %08X\n", da2_hwcursor_latch.addr); - - // da2_log("ADDR %08X\n",hwcursor_addr); } if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) da2->con = 1; @@ -2933,7 +2793,6 @@ da2_reset(void* priv) da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ da2->ma_latch = 0; - //da2->gdcramlatched = 0; da2->interlace = 0; da2->attrregs[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ da2->attr_palette_enable = 0; /* disable attribute generator */ @@ -2964,9 +2823,7 @@ static void *da2_init() int memsize = 1024 * 1024; da2->vram = malloc(memsize); da2->vram_mask = memsize - 1; - //da2->gram_display_mask = (memsize - 1) >> 3; da2->cram = malloc(0x1000); - //da2->cram_display_mask = 0x1000 - 1; da2->vram_display_mask = DA2_MASK_CRAM; da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h da2_loadfont(DA2_FONTROM_PATH, da2); @@ -3052,6 +2909,7 @@ void da2_close(void *p) fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); fclose(f); } +#endif #ifdef ENABLE_DA2_DEBUGBLT f = fopen("da2_bltdump.csv", "w"); if (f != NULL && da2->bitblt.debug_reg_ip > 0) { @@ -3078,7 +2936,6 @@ void da2_close(void *p) if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); free(da2->bitblt.debug_reg); -#endif #endif free(da2->cram); free(da2->vram); @@ -3100,31 +2957,6 @@ void da2_force_redraw(void *p) da2->fullchange = changeframecount; } -//void da2_add_status_info(char *s, int max_len, void *p) -//{ -// da2_t* da2 = (da2_t*)p; -// char temps[128]; -// if (!(da2->pos_regs[2] & 0x01)) strcpy(temps, "Render: DA2 disabled\n"); -// else if (da2->render == da2_render_blank) strcpy(temps, "Render: DA2 blank\n"); -// else if (da2->render == da2_render_text) strcpy(temps, "Render: DA2 text (mode 8 or E)\n"); -// else if (da2->render == da2_render_textm3) strcpy(temps, "Render: DA2 EGA compatible text (mode 3)\n"); -// else if (da2->render == da2_render_color_4bpp) strcpy(temps, "Render: DA2 4 bpp graphics (mode A or D)\n"); -// else if (da2->render == da2_render_color_8bpp) strcpy(temps, "Render: DA2 8 bpp graphics (mode F)\n"); -// else strcpy(temps, "Render: DA2 unknown render\n"); -// strncat(s, temps, max_len); -// -// sprintf(temps, "Resolution : %i x %i\n", da2->video_res_x, da2->video_res_y); -// strncat(s, temps, max_len); -// -// sprintf(temps, "Refresh rate : %i Hz\n", da2->frames); -// da2->frames = 0; -// strncat(s, temps, max_len); -// -// sprintf(temps, "Render lines : %i\n\n", da2->writelines); -// da2->writelines = 0; -// strncat(s, temps, max_len); -//} - const device_t ps55da2_device = { .name = "IBM Display Adapter II (MCA)", .internal_name = "ps55da2", From 6aec2f04dd548e97a55a71968cca8f912744295c Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:07:24 +0900 Subject: [PATCH 11/82] Fixed ESDI hung-up issue when ctrl+alt+del reset --- src/disk/hdc_esdi_mca.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 047089a1e..bdb037fee 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1259,9 +1259,12 @@ esdi_mca_feedb(void *priv) static void esdi_reset(void* priv) { esdi_t* dev = (esdi_t*)priv; - dev->in_reset = 1; - esdi_mca_set_callback(dev, ESDI_TIME * 50); - dev->status = STATUS_BUSY; + pclog("esdi reset %d %x\n", dev->in_reset, dev->status); + if (!dev->in_reset) { + dev->in_reset = 1; + esdi_mca_set_callback(dev, ESDI_TIME * 50); + dev->status = STATUS_BUSY; + } } static void * @@ -1272,6 +1275,7 @@ esdi_init(UNUSED(const device_t *info)) uint8_t c; uint8_t i; + pclog("esdi init\n"); dev = malloc(sizeof(esdi_t)); if (dev == NULL) return (NULL); @@ -1334,9 +1338,9 @@ esdi_init(UNUSED(const device_t *info)) /* The slot number of this controller is fixed by the planar. IBM PS/55 5551-T assigns it #5. */ int slotno = device_get_config_int("in_esdi_slot"); if (slotno) - mca_add_to_slot(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, NULL, dev, slotno - 1); + mca_add_to_slot(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, esdi_reset, dev, slotno - 1); else - mca_add(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, NULL, dev); + mca_add(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, esdi_reset, dev); } else mca_add(esdi_mca_read, esdi_mca_write, esdi_mca_feedb, NULL, dev); @@ -1348,6 +1352,7 @@ esdi_init(UNUSED(const device_t *info)) /* Set the reply timer. */ timer_add(&dev->timer, esdi_callback, dev, 0); + pclog("esdi init finish\n"); return dev; } From 3c6695cdeafb5b6fbf5a1e98c2747f4e9054d861 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:08:51 +0900 Subject: [PATCH 12/82] Removed debug logging --- src/disk/hdc_esdi_mca.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index bdb037fee..adc5cd6a0 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1259,7 +1259,6 @@ esdi_mca_feedb(void *priv) static void esdi_reset(void* priv) { esdi_t* dev = (esdi_t*)priv; - pclog("esdi reset %d %x\n", dev->in_reset, dev->status); if (!dev->in_reset) { dev->in_reset = 1; esdi_mca_set_callback(dev, ESDI_TIME * 50); @@ -1275,7 +1274,6 @@ esdi_init(UNUSED(const device_t *info)) uint8_t c; uint8_t i; - pclog("esdi init\n"); dev = malloc(sizeof(esdi_t)); if (dev == NULL) return (NULL); @@ -1352,7 +1350,6 @@ esdi_init(UNUSED(const device_t *info)) /* Set the reply timer. */ timer_add(&dev->timer, esdi_callback, dev, 0); - pclog("esdi init finish\n"); return dev; } From c3b2ddfcb18d0414b06b03ee161e3ec6a1eee4b7 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:56:25 +0900 Subject: [PATCH 13/82] added comment for 5576 keyb --- src/device/keyboard_at.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 2900ec17a..161a13e0c 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -1631,21 +1631,23 @@ static const scancode scancode_set3[512] = { }; /* IBM Japan 5576-001, 002 and 003 keyboards have three extra scancode sets; 81h, 82h, 8ah. - Scancode set 81h and 82h are not implemented yet. To implement them, we need take the following into consideration. * Add a UI to switch the type of keyboards and keyboard IDs. * Add modified scancode set 1 and 2 (in these modes, language input keys are used as an alternative key). - * Japanese keyboards traditionally use a typewriter layout. Its key mapping doesn't match with foreign keyboards. + * Japanese keyboards traditionally use a bit-paired layout. Its key mapping doesn't match with foreign keyboards. 5576 keyboards kept 101-key compatible scancode sets because PS/55 had to support western (PS/2) versions of operating systems. The default scancode set is 2. In Japanese DOS, the keyboard driver confirms its keyboard ID, and sends a command to switch the scancode set to 8Ah. + Japanese OS/2 and Windows use the scancode set 82h. - The OADG standard and modern Japanese keyboards use the same keyboard ID and scancode set number as PS/2 keyboards use. + The OADG standard (1991-) and modern Japanese keyboards use the same keyboard ID and scancode set number as PS/2 keyboards use. Three extra scancode sets are no longer available. Instead, language input keys are available in scancode set 1 and 2. - However, it has a different key mapping. + However, their physical key layout is a bit-paired layout. Users have to choose the correct keyboard layout on setup, and the driver needs to remap keys. + Currently, scancode set 81h and 82h are not implemented yet. Also, the key layout is designed to match with the Japanese keyboard. + [Japanese DOS and keyboard scancode set] | | K3.3 | J4.0 | J5.0 | J4.0/V | J5.0/V | OS/2 J1.3 | PC DOS 5 | |---------------------------|:----:|:----:|:----:|:------:|:------:|:---------:|:--------:| From 351d8c8441b5d32a88b601a2fd306595933dcbe4 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 17 Aug 2024 00:37:19 +0900 Subject: [PATCH 14/82] added i/o port 3e9 write --- src/video/vid_ps55da2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index c5e64694d..143c478dc 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1022,6 +1022,10 @@ void da2_out(uint16_t addr, uint16_t val, void *p) } da2->attrff ^= 1; break; + case 0x3E9: + /* VZ Editor's CURSOR.COM writes via this port */ + da2->attrregs[da2->attraddr & 0x3f] = val; + break; case LG_INDEX: da2->gdcaddr = val; break; From 2c8c519b82135c7e3332a4621b9718c06cbe8f83 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 17 Aug 2024 00:38:32 +0900 Subject: [PATCH 15/82] Removed debug logging --- src/video/vid_vga.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 699cfe85e..8d4439f95 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -108,7 +108,6 @@ void vga_disable(void* p) vga_t* vga = (vga_t*)p; svga_t* svga = &vga->svga; - pclog("vga_disable %04X:%04X\n", cs >> 4, cpu_state.pc); io_removehandler(0x03a0, 0x0040, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); mem_mapping_disable(&svga->mapping); svga->vga_enabled = 0; @@ -119,7 +118,6 @@ void vga_enable(void* p) vga_t* vga = (vga_t*)p; svga_t* svga = &vga->svga; - pclog("vga_enable %04X:%04X\n", cs >> 4, cpu_state.pc); io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); if (!(svga->miscout & 1)) io_sethandler(0x03a0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); From ee280e10f1da6bfb5798593c1c8f90d00e23c154 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 17 Aug 2024 00:39:40 +0900 Subject: [PATCH 16/82] removed debug logging --- src/floppy/fdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index a878853e4..af1aa37c6 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -777,7 +777,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 5: /*Command register*/ if (fdc->fifointest) { - pclog("FIFO buffer position = %X\n", ((fifo_t *)fdc->fifo_p)->end); + fdc_log("FIFO buffer position = %X\n", ((fifo_t *)fdc->fifo_p)->end); fifo_write(val, fdc->fifo_p); if (fifo_get_full(fdc->fifo_p)) fdc->stat &= ~0x80; From 05e663a5c30c715bb47d733c1e06bb57c031a016 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:34:26 +0900 Subject: [PATCH 17/82] merged ps55 fdc with ps2 fdc --- src/floppy/fdc.c | 27 +++++++++++++-------------- src/machine/m_ps2_mca.c | 20 ++------------------ 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index af1aa37c6..f317fd948 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -734,10 +734,10 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) drive = real_drive(fdc, fdc->dor & 3); fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); } - /* FIFO test mode (PS/55 only? This is not documented in neither the PS/2 HITR nor the 82077AA datasheet.) + /* Bit 2: FIFO test mode (PS/55 only? This is not documented in neither the PS/2 HITR nor the 82077AA datasheet.) The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h. If it fails, then floppy drives will be treated as DD drives. */ - if (fdc->flags & FDC_FLAG_PS55) { + if (fdc->flags & FDC_FLAG_PS2) { if (val & 0x04) { fdc->tfifo = 8; @@ -1272,7 +1272,7 @@ fdc_read(uint16_t addr, void *priv) if (fdc->fintr || fdc->reset_stat) /* INTR */ ret |= 0x80; } - else if (fdc->flags & FDC_FLAG_PS55) { + else if (fdc->flags & FDC_FLAG_PS2) { /* Status Register A (PS/2, PS/55) */ /* | INT PEND | nDRV2 | STEP | nTRK0 | HDSEL | nIDX | nWP | DIR | */ ret = 0x04; @@ -1320,7 +1320,7 @@ fdc_read(uint16_t addr, void *priv) break; } } - else if (fdc->flags & FDC_FLAG_PS55) { + else if (fdc->flags & FDC_FLAG_PS2) { /* Status Register B (PS/2, PS/55) */ /* | 1 | 1 | DS0 | WD TOGGLE | RD TOGGLE | WE | MOT EN1 | MOT EN0 | */ ret = 0xc0; @@ -1381,7 +1381,7 @@ fdc_read(uint16_t addr, void *priv) else ret = 0x00; } - else if (fdc->flags & FDC_FLAG_PS55) { + else if (fdc->flags & FDC_FLAG_PS2) { /* error when ret = 1, 2*/ ret = (fdc->fifointest) ? 4 : 0; } @@ -1442,7 +1442,7 @@ fdc_read(uint16_t addr, void *priv) } else ret = 0x00; } - else if (fdc->flags & FDC_FLAG_PS55) { + else if (fdc->flags & FDC_FLAG_PS2) { /* Digital Input Register (PS/2, PS/55) */ /* | DSKCHG | 1 | 1 | 1 | 1 | DRATE1 | DRATE0 | nHDEN | */ ret = 0x78; @@ -1484,7 +1484,7 @@ static void fdc_poll_common_finish(fdc_t *fdc, int compare, int st5) { fdc_int(fdc, 1); - if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55))) + if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS2))) fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; @@ -1786,7 +1786,7 @@ fdc_callback(void *priv) } else { fdc->interrupt = -2; fdc_int(fdc, 1); - if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55))) + if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS2))) fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->drive; @@ -1878,7 +1878,7 @@ fdc_error(fdc_t *fdc, int st5, int st6) timer_disable(&fdc->timer); fdc_int(fdc, 1); - if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55))) + if (!(fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS2))) fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = 0x40 | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; @@ -2042,7 +2042,6 @@ fdc_noidam(fdc_t *fdc) void fdc_nosector(fdc_t *fdc) { - pclog("nosector error\n"); fdc_error(fdc, 4, 0); } @@ -2288,7 +2287,7 @@ fdc_reset(void *priv) fdc->enable_3f1 = 1; fdc_update_enh_mode(fdc, 0); - if (fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS55)) + if (fdc->flags & (FDC_FLAG_PS1 | FDC_FLAG_PS2)) fdc_update_densel_polarity(fdc, 0); else fdc_update_densel_polarity(fdc, 1); @@ -2631,11 +2630,11 @@ const device_t fdc_at_ps1_2121_device = { .config = NULL }; -const device_t fdc_at_ps55_device = { - .name = "PC/AT Floppy Drive Controller (PS/55)", +const device_t fdc_at_ps2_device = { + .name = "PC/AT Floppy Drive Controller (PS/2 internal)", .internal_name = "fdc_at_ps55", .flags = 0, - .local = FDC_FLAG_AT | FDC_FLAG_PS55, + .local = FDC_FLAG_AT | FDC_FLAG_PS2, .init = fdc_init, .close = fdc_close, .reset = fdc_reset, diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index fc2e3313b..72776b22d 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1557,7 +1557,7 @@ machine_ps2_common_init(const machine_t *model) machine_common_init(model); if (fdc_current[0] == FDC_INTERNAL) - device_add(&fdc_at_device); + device_add(&fdc_at_ps2_device); dma16_init(); ps2_dma_init(); @@ -1801,23 +1801,7 @@ machine_ps55_model_50t_init(const machine_t* model) if (bios_only || !ret) return ret; - /* begin ps2 common init */ - machine_common_init(model); - - device_add(&fdc_at_ps55_device); - - dma16_init(); - ps2_dma_init(); - device_add(&ps_no_nmi_nvr_device); - pic2_init(); - - int pit_type = ((pit_mode == -1 && is486) || pit_mode == 1) ? PIT_8254_FAST : PIT_8254; - pit_ps2_init(pit_type); - - nmi_mask = 0x80; - - ps2.uart = device_add_inst(&ns16550_device, 1); - /* end ps2 common init */ + machine_ps2_common_init(model); /* * Planar ID From 60a84cfb5bc948dbfa71a7f62354ea21b885ffb0 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 15 Nov 2024 21:53:20 +0900 Subject: [PATCH 18/82] +character drawing in bitblt (experimental) * Changed comment format. * Updated Font ROM map written in comment --- src/video/vid_ps55da2.c | 514 ++++++++++++++++++++++++++-------------- 1 file changed, 337 insertions(+), 177 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 143c478dc..6a90a3dc3 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -39,16 +39,19 @@ #define DA2_FONTROM_PATH "roms/video/da2/PS55FNTJ.BIN" #define DA2_FONTROM_SIZE 1024*1024 +#define DA2_FONTROM_BASESBCS 0x98000 +#define DA2_GAIJIRAM_SBCS 0x34000 +#define DA2_GAIJIRAM_SBEX 0x3c000 #define DA2_MASK_MMIO 0x1ffff #define DA2_MASK_GRAM 0x1ffff #define DA2_MASK_CRAM 0xfff #define DA2_MASK_GAIJIRAM 0x3ffff #define DA2_PIXELCLOCK 58000000.0 -#define DA2_BLT_MEMSIZE 0x80 +#define DA2_BLT_MEMSIZE 0x100 #define DA2_BLT_REGSIZE 0x40 #define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) -#define DA2_DEBUG_BLTLOG_MAX 256*1024 -#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe +#define DA2_DEBUG_BLTLOG_MAX 256*1024 +#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe #define DA2_DEBUG_BLT_USEDRESET 0xfefefe #define DA2_BLT_CIDLE 0 @@ -56,8 +59,9 @@ #define DA2_BLT_CFILLTILE 2 #define DA2_BLT_CCOPYF 3 #define DA2_BLT_CCOPYR 4 -#define DA2_BLT_CDONE 5 -#define DA2_BLT_CLOAD 6 +#define DA2_BLT_CPUTCHAR 5 +#define DA2_BLT_CDONE 6 +#define DA2_BLT_CLOAD 7 /* POS ID = 0xeffe : Display Adapter II, III, V */ #define DA2_POSID_H 0xef #define DA2_POSID_L 0xfe @@ -124,9 +128,9 @@ #define LS_CONFIG1 0x0a #define LS_CONFIG2 0x0b /* added */ #define LF_INDEX 0x3e2 -#define LF_DATA 0x3e3 -#define LF_MMIO_SEL 0x08 /* added */ -#define LF_MMIO_ADDR 0x0A /* added */ +#define LF_DATA 0x3e3 +#define LF_MMIO_SEL 0x08 /* added */ +#define LF_MMIO_ADDR 0x0A /* added */ #define LF_MMIO_MODE 0x0B /* added */ #define LC_INDEX 0x3E4 #define LC_DATA 0x3E5 @@ -212,27 +216,31 @@ #define LG_MAP_MASKJ 0x0A #define LG_COMMAND 0x0B #define LG_SET_RESET_2 0x10 - -#ifdef ENABLE_DA2_LOG -int da2_do_log = ENABLE_DA2_LOG; - -static void -da2_log(const char* fmt, ...) -{ - va_list ap; - - if (da2_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -# define da2_log(fmt, ...) + +#ifndef RELEASE_BUILD +#define ENABLE_DA2_LOG 1 +#endif + +#ifdef ENABLE_DA2_LOG +int da2_do_log = ENABLE_DA2_LOG; + +static void +da2_log(const char* fmt, ...) +{ + va_list ap; + + if (da2_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define da2_log(fmt, ...) +#endif +#ifndef RELEASE_BUILD +# define ENABLE_DA2_DEBUGBLT 1 #endif -#ifndef RELEASE_BUILD -# define ENABLE_DA2_DEBUGBLT 1 -#endif typedef struct da2_t { @@ -246,7 +254,7 @@ typedef struct da2_t uint8_t gdcreg[64]; uint8_t reg3ee[16]; int gdcaddr; - uint8_t attrregs[0x40]; + uint8_t attrc[0x40]; int attraddr, attrff; int attr_palette_enable; //uint8_t seqregs[64]; @@ -300,7 +308,7 @@ typedef struct da2_t pc_timer_t timer; uint64_t da2const; - uint8_t scrblank; + //uint8_t scrblank; int dispon; int hdisp_on; @@ -329,7 +337,7 @@ typedef struct da2_t uint32_t vram_display_mask; uint32_t banked_mask; - uint32_t write_bank, read_bank; + //uint32_t write_bank, read_bank; int fullchange; @@ -337,7 +345,7 @@ typedef struct da2_t /*If set then another device is driving the monitor output and the SVGA card should not attempt to display anything */ - int override; + int override; /* end VGA compatible regs*/ struct @@ -348,12 +356,12 @@ typedef struct da2_t uint8_t font[DA2_FONTROM_SIZE]; } mmio; - mem_mapping_t linear_mapping; + //mem_mapping_t linear_mapping; - uint32_t bank[2]; - uint32_t mask; + //uint32_t bank[2]; + //uint32_t mask; - int type; + //int type; struct { int bitshift_destr; @@ -386,7 +394,7 @@ typedef struct da2_t uint8_t pos_regs[8]; svga_t *mb_vga; - int vidsys_ena; + //int vidsys_ena; int old_pos2; } da2_t; @@ -406,7 +414,7 @@ typedef union { typedef struct { uint32_t p8[8]; } pixel32; - + /* safety read for internal functions */ uint32_t DA2_readvram_s(uint32_t addr, da2_t* da2) { @@ -505,6 +513,22 @@ void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } +void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) +{ + pixel32 srcpx; + if (srcaddr >= DA2_FONTROM_SIZE) { + da2_log("DA2 Putchar Addr Error %x\n", srcaddr); + return; + } + for (int i = 0; i < 8; i++) + srcpx.p8[i] = ((uint32_t)da2->mmio.font[srcaddr] << 24) + | ((uint32_t)da2->mmio.font[srcaddr + 1] << 16) + | ((uint32_t)da2->mmio.font[srcaddr + 2] << 8) + | ((uint32_t)da2->mmio.font[srcaddr + 3] << 0);//read in word + + DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +#ifdef ENABLE_DA2_DEBUGBLT uint8_t pixel1tohex(uint32_t addr, int index, da2_t* da2) { uint8_t pixeldata = 0; for (int j = 0; j < 8; j++) { @@ -515,15 +539,58 @@ uint8_t pixel1tohex(uint32_t addr, int index, da2_t* da2) { void print_pixelbyte(uint32_t addr, da2_t* da2) { for (int i = 0; i < 8; i++) { - da2_log("%X", pixel1tohex(addr, i, da2)); + pclog("%X", pixel1tohex(addr, i, da2)); } } - +void print_bytetobin(uint8_t b) { + for (int i = 0; i < 8; i++) + { + if(b & 0x80) + pclog("1"); + else + pclog("0"); + b <<= 1; + } +} +//Convert internal char code to Shift JIS code +inline int isKanji1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); } +inline int isKanji2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); } +uint16_t IBMJtoSJIS(uint16_t knj) +{ + if (knj < 0x100) return 0xffff; + knj -= 0x100; + if (knj <= 0x1f7d) + ;/* do nothing */ + else if (knj >= 0xb700 && knj <= 0xb75f) { + knj -= 0x90ec; + } + else if (knj >= 0xb3f0 && knj <= 0xb67f) { + knj -= 0x906c; + } + else if (knj >= 0x8000 && knj <= 0x8183) + { + knj -= 0x5524; + } + else + return 0xffff; + uint32_t knj1 = knj / 0xBC; + uint32_t knj2 = knj - (knj1 * 0xBC); + knj1 += 0x81; + if (knj1 > 0x9F) knj1 += 0x40; + knj2 += 0x40; + if (knj2 > 0x7E) knj2++; + //if (!isKanji1(knj1)) return 0xffff; + //if (!isKanji2(knj2)) return 0xffff; + knj = knj1 << 8; + knj |= knj2; + return knj; +} +#endif void da2_bitblt_load(da2_t* da2) { uint32_t value32; uint64_t value64; - //da2_log("BITBLT loading params\n"); + da2_log("BITBLT loading params\n"); //da2_log("BitBlt memory:\n"); //if (da2->bitblt.payload[0] != 0) // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) @@ -544,7 +611,7 @@ void da2_bitblt_load(da2_t* da2) value32 = da2->bitblt.payload[i + 3]; value32 <<= 8; value32 |= da2->bitblt.payload[i + 2]; - //da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; i += 3; break; @@ -556,7 +623,7 @@ void da2_bitblt_load(da2_t* da2) value32 |= da2->bitblt.payload[i + 3]; value32 <<= 8; value32 |= da2->bitblt.payload[i + 2]; - //da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; i += 5; break; @@ -573,8 +640,8 @@ void da2_bitblt_load(da2_t* da2) value64 <<= 8; value64 |= da2->bitblt.payload[i + 2]; da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; - //da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - //da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); i += 7; break; case 0x00: @@ -635,14 +702,50 @@ void da2_bitblt_load(da2_t* da2) da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); da2->bitblt.exec = DA2_BLT_CDONE; } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {//Fill a rectangle (or draw a line) + else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ + da2->bitblt.exec = DA2_BLT_CPUTCHAR; + /* Todo: addressing */ + //if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; + //{ + // da2->bitblt.destaddr += 2; + // da2->bitblt.size_x -= 1; + // da2->bitblt.destpitch += 2; + // da2->bitblt.srcpitch += 2; + //} + uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2; + da2->bitblt.destaddr += 2; + da2->bitblt.srcpitch = 0; + da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ + da2->bitblt.bitshift_destr += 1; + da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); + } + else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { + da2->bitblt.exec = DA2_BLT_CPUTCHAR; + uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; + da2->bitblt.destaddr += 2; + da2->bitblt.srcpitch = 0; + da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ + da2->bitblt.bitshift_destr += 1; + da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {/* Fill a rectangle(or draw a line) */ da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); da2->bitblt.exec = DA2_BLT_CFILLRECT; da2->bitblt.destaddr += 2; } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) {//Tiling a rectangle ??(transfer tile data multiple times) os/2 only + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */ da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; @@ -653,7 +756,7 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) {//Tiling a rectangle (transfer tile data multiple times) + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle (transfer tile data multiple times) */ da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; @@ -664,7 +767,7 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) {//Block transfer (range copy) + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) {/* Block transfer (range copy) */ da2->bitblt.exec = DA2_BLT_CCOPYF; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr += 2; @@ -674,7 +777,7 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) {//Block copy but reversed direction + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) {/* Block copy but reversed direction */ da2->bitblt.exec = DA2_BLT_CCOPYR; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr -= 2; @@ -686,11 +789,6 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.size_x, da2->bitblt.size_y); //da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); } - //do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle - while (timer_is_enabled(&da2->bitblt.timer) && da2->bitblt.exec != DA2_BLT_CDONE) - { - da2_bitblt_exec(da2); - } } } void da2_bitblt_exec(void* p) @@ -704,8 +802,8 @@ void da2_bitblt_exec(void* p) timer_disable(&da2->bitblt.timer); break; case DA2_BLT_CLOAD: - da2_bitblt_load(da2); da2->bitblt.indata = 0; + da2_bitblt_load(da2); break; case DA2_BLT_CFILLRECT: //da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); @@ -799,8 +897,47 @@ void da2_bitblt_exec(void* p) da2->bitblt.destaddr -= 2; da2->bitblt.srcaddr -= 2; break; + case DA2_BLT_CPUTCHAR: + //da2->bitblt.y += 2; + da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; + pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); + //da2->bitblt.srcaddr += 2; + if(da2->bitblt.reg[0x12] < 0x100) + da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; + else + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; + print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); + print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); + pclog("\n"); + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + //if (1) { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 3) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += 130; + //da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + //da2->bitblt.srcaddr += -1; + } + else if (da2->bitblt.x == 0) { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + //da2->bitblt.x++; + } + else { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + //da2->bitblt.x++; + } + //da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2; + ////da2->bitblt.srcaddr += 2; + //da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; + break; case DA2_BLT_CDONE: - //initialize regs with fefefefeh, clear regs with fefeh for debug dump + /* initialize regs for debug dump */ for (int i = 0; i < DA2_BLT_REGSIZE; i++) { if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; } @@ -809,6 +946,21 @@ void da2_bitblt_exec(void* p) break; } } +void da2_bitblt_dopayload(da2_t* da2) { + if (da2->bitblt.exec == DA2_BLT_CIDLE) + { + da2->bitblt.exec = DA2_BLT_CLOAD; + //timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ + da2_log("da2 Do bitblt\n"); + while (da2->bitblt.exec != DA2_BLT_CIDLE) + { + da2_bitblt_exec(da2); + } + da2_log("da2 End bitblt %x\n", da2->bitblt.exec); + } +} + void da2_out(uint16_t addr, uint16_t val, void *p) { da2_t *da2 = (da2_t *)p; @@ -867,8 +1019,8 @@ void da2_out(uint16_t addr, uint16_t val, void *p) case LS_DATA: //da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->ioctladdr, val, cs >> 4, cpu_state.pc); if (da2->ioctladdr > 0xf) return; - //if (da2->ioctl[da2->ioctladdr & 15] != val) - // da2_log("ioctl changed %x: %x -> %x %04X:%04X\n", da2->ioctladdr & 15, da2->ioctl[da2->ioctladdr & 15], val, cs >> 4, cpu_state.pc); + if (da2->ioctl[da2->ioctladdr & 15] != val) + da2_log("ioctl changed %x: %x -> %x %04X:%04X\n", da2->ioctladdr & 15, da2->ioctl[da2->ioctladdr & 15], val, cs >> 4, cpu_state.pc); oldval = da2->ioctl[da2->ioctladdr]; da2->ioctl[da2->ioctladdr] = val; if (oldval != val) { @@ -882,12 +1034,7 @@ void da2_out(uint16_t addr, uint16_t val, void *p) } else if (da2->ioctladdr == LS_MMIO && (!(val & 0x01))) /* MMIO register */ { - da2->bitblt.indata = 1; - if (da2->bitblt.exec == DA2_BLT_CIDLE) - { - da2->bitblt.exec = DA2_BLT_CLOAD; - timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - } + //da2->bitblt.indata = 1; } } break; @@ -910,8 +1057,8 @@ void da2_out(uint16_t addr, uint16_t val, void *p) break; case LC_DATA: if (da2->crtcaddr > 0x1f) return; - if (!(da2->crtcaddr == LC_CURSOR_LOC_HIGH || da2->crtcaddr == LC_CURSOR_LOC_LOWJ)) - da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc); + //if (!(da2->crtcaddr == LC_CURSOR_LOC_HIGH || da2->crtcaddr == LC_CURSOR_LOC_LOWJ)) + // da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc); if (!(da2->crtc[da2->crtcaddr] ^ val)) return; switch (da2->crtcaddr) { case LC_CRTC_OVERFLOW: @@ -955,10 +1102,10 @@ void da2_out(uint16_t addr, uint16_t val, void *p) } break; case LV_PORT: - da2_log("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc); + //da2_log("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc); if (!da2->attrff) { - // da2->attraddr = val & 31; + // da2->attraddr = val & 31; da2->attraddr = val & 0x3f; if ((val & 0x20) != (da2->attr_palette_enable & 0x20)) { @@ -970,47 +1117,44 @@ void da2_out(uint16_t addr, uint16_t val, void *p) } else { - if ((da2->attraddr == LV_PANNING) && (da2->attrregs[LV_PANNING] != val)) + if ((da2->attraddr == LV_PANNING) && (da2->attrc[LV_PANNING] != val)) da2->fullchange = changeframecount; - if (da2->attrregs[da2->attraddr & 0x3f] != val) - da2_log("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrregs[da2->attraddr & 0x3f], val); - da2->attrregs[da2->attraddr & 0x3f] = val; - //da2_log("set attrreg %x: %x\n", da2->attraddr & 31, val); + if (da2->attrc[da2->attraddr & 0x3f] != val) + da2_log("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrc[da2->attraddr & 0x3f], val); + da2->attrc[da2->attraddr & 0x3f] = val; + //da2_log("set attrc %x: %x\n", da2->attraddr & 31, val); if (da2->attraddr < 16) da2->fullchange = changeframecount; - //if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr == 0x14 || da2->attraddr < 0x10) if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) { for (int c = 0; c < 16; c++) { - //if (da2->attrregs[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrregs[c] & 0xf) | ((da2->attrregs[0x14] & 0xf) << 4); - //else da2->egapal[c] = (da2->attrregs[c] & 0x3f) | ((da2->attrregs[0x14] & 0xc) << 4); - if (da2->attrregs[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = da2->attrregs[c] & 0xf; - else da2->egapal[c] = da2->attrregs[c] & 0x3f; - } - } - if (da2->attraddr == LV_COLOR_PLANE_ENAB) - { - if ((val & 0xff) != da2->plane_mask) - da2->fullchange = changeframecount; - da2->plane_mask = val & 0xff; - } - if (da2->attraddr == LV_CURSOR_CONTROL) - { - switch (val & 0x18) { - case 0x08://fast blink - da2->blinkconf = 0x10; - break; - case 0x18://slow blink - da2->blinkconf = 0x20; - break; - default://no blink - da2->blinkconf = 0xff; - break; + //if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4); + //else da2->egapal[c] = (da2->attrc[c] & 0x3f) | ((da2->attrc[0x14] & 0xc) << 4); + if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = da2->attrc[c] & 0xf; + else da2->egapal[c] = da2->attrc[c] & 0x3f; } } switch (da2->attraddr) { + case LV_COLOR_PLANE_ENAB: + if ((val & 0xff) != da2->plane_mask) + da2->fullchange = changeframecount; + da2->plane_mask = val & 0xff; + break; + case LV_CURSOR_CONTROL: + switch (val & 0x18) { + case 0x08://fast blink + da2->blinkconf = 0x10; + break; + case 0x18://slow blink + da2->blinkconf = 0x20; + break; + default://no blink + da2->blinkconf = 0xff; + break; + } + break; case LV_MODE_CONTROL: case LV_ATTRIBUTE_CNTL: case LV_COMPATIBILITY: @@ -1022,9 +1166,9 @@ void da2_out(uint16_t addr, uint16_t val, void *p) } da2->attrff ^= 1; break; - case 0x3E9: - /* VZ Editor's CURSOR.COM writes via this port */ - da2->attrregs[da2->attraddr & 0x3f] = val; + case 0x3E9: + /* VZ Editor's CURSOR.COM writes data via this port */ + da2->attrc[da2->attraddr & 0x3f] = val; break; case LG_INDEX: da2->gdcaddr = val; @@ -1103,15 +1247,17 @@ uint16_t da2_in(uint16_t addr, void *p) if (da2->ioctladdr > 0xf) return 0xff; temp = da2->ioctl[da2->ioctladdr]; if (da2->ioctladdr == LS_STATUS) { /* Status register */ - if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 0x50 && da2->attrregs[LV_COMPATIBILITY] & 0x08) + if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 0x50 && da2->attrc[LV_COMPATIBILITY] & 0x08) temp &= 0x7F; /* Inactive when the RGB output voltage is high(or the cable is not connected to the color monitor). */ else temp |= 0x80; /* Active when the RGB output voltage is lowand the cable is connected to the color monitor. If the cable or the monitor is wrong, it becomes inactive. */ temp &= 0xf6;//idle + if (da2->bitblt.indata) /* for OS/2 J1.3 */ + da2_bitblt_dopayload(da2); if (da2->bitblt.exec != DA2_BLT_CIDLE) { - //da2_log("exec:%d\n", da2->bitblt.exec); + //da2_log("exec:%x\n", da2->bitblt.exec); temp |= 0x08;//wait(bit 3 + bit 0) //if (!da2->bitblt.timer.enabled) //{ @@ -1152,7 +1298,7 @@ uint16_t da2_in(uint16_t addr, void *p) temp = da2->cgastat; } else - temp = da2->attrregs[da2->attraddr]; + temp = da2->attrc[da2->attraddr]; //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->attraddr, temp, cs >> 4, cpu_state.pc); da2->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */ break; @@ -1161,7 +1307,7 @@ uint16_t da2_in(uint16_t addr, void *p) break; case LG_DATA: temp = da2->gdcreg[da2->gdcaddr & 0x1f]; - da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc); + //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc); break; } //da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); @@ -1386,12 +1532,18 @@ Bank 1, 2, 3 Bank 4 * -0DB6Fh ( 4800-8DB6Fh;IBMJ 100-1F7Dh) : JIS X 0208 DBCS (24 x 24) 10000-16D1Fh (90000-96D1Fh;IBMJ 2000-2183h) : IBM Extended Characters -18000-1BFFFh (98000-9BFFFh;around IBMJ 21C7-22AAh) : JIS X 0201 SBCS (13 x 30) -1FD20- * +18000-1BFCFh (98000-9BFCFh;around IBMJ 21C7-22AAh) : JIS X 0201 SBCS (13 x 30) +1C000-1FFFFh (9C000-9FFFFh;around IBMJ 22AA-238Eh) : Codepage 437 characters (13 x 30) Bank 5 +00000-0C68Fh (A0000-AC68Fh;around IBMJ 238E-2650h) : Gaiji (24 x 24) + * -0D09Fh (9FD20-AD09Fh;IBMJ 2384-2673h) : Gaiji 752 chs (maybe blank) 10000-13FFFh (B0000-B3FFFh;around IBMJ 271C-27FFh) : Extended SBCS (13 x 30) -14000-146FFh (B4000-B46FFh;IBMJ 2800-2818h) : Half-width box drawing characters (7 lines * 4 parts * 64 bytes) used by DOS Bunsho + +14000-147FFh (B4000-B46FFh;IBMJ 2800-2818h) : Half-width box drawing characters (7 lines * 4 parts * 64 bytes) used by DOS Bunsho +16000-17FFFh (B6000-B7FFFh;around IBMJ h) : Codepage 850 characters (13 x 30) +18000-1A3FFh (B8000-BA3FFh;around IBMJ h) : Shape Icons? (32 x 32) + (B9580-?;IBMJ 2930-295e?) : Full-width box drawing characters The signature 80h, 01h must be placed at Bank 0:1AFFEh to run OS/2 J1.3. @@ -1470,7 +1622,7 @@ uint8_t getPS55ForeColor(uint8_t attr, da2_t* da2) foreground <<= 2; //0010 0000 foreground |= ~attr & 0xc0;// 1110 0000 foreground >>= 4;//0000 1110 - if (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;//bright color palette + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;//bright color palette return foreground; } @@ -1510,7 +1662,7 @@ static void da2_render_text(da2_t* da2) chr = da2->cram[(da2->ma) & da2->vram_display_mask]; attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; //if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); - if (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80)//IO 3E8h, Index 1Dh + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80)//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, da2); @@ -1561,9 +1713,9 @@ static void da2_render_text(da2_t* da2) // the char code is SBCS (ANK) uint32_t fontbase; if (attr & 0x02)//second map of SBCS font - fontbase = 0x3c000; + fontbase = DA2_GAIJIRAM_SBEX; else - fontbase = 0x34000; + fontbase = DA2_GAIJIRAM_SBCS; uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font font <<= 8; font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font @@ -1587,25 +1739,25 @@ static void da2_render_text(da2_t* da2) chr_wide = 0; } //Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. - if (da2->sc == 27 && attr & 0x40 && ~da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) {//Underscore only in monochrome mode + if (da2->sc == 27 && attr & 0x40 && ~da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) {//Underscore only in monochrome mode for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[fg]];//under line (white) } //Column 1 (Vertical Line) if (attr & 0x10) { - p[0] = da2->pallook[da2->egapal[(da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[LV_GRID_COLOR_0]) : 2]];//vertical line (white) + p[0] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];//vertical line (white) } - if (da2->sc == 0 && attr & 0x20 && ~da2->attrregs[LV_PAS_STATUS_CNTRL]) {//HGrid + if (da2->sc == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) {//HGrid for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[(da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[LV_GRID_COLOR_0]) : 2]];//horizontal line (white) + p[n] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];//horizontal line (white) } //Drawing text cursor drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) { int cursorwidth = (da2->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); - int cursorcolor = (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[LV_CURSOR_COLOR]) : 2;//Choose color 2 if mode 8 - fg = (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2); + int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2;//Choose color 2 if mode 8 + fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2); bg = 0; if (attr & 0x04) {//Color 0 if reverse bg = fg; @@ -1677,7 +1829,7 @@ static void da2_render_textm3(da2_t* da2) else { // the char code is SBCS (ANK) uint32_t fontbase; - fontbase = 0x34000; + fontbase = DA2_FONTROM_BASESBCS; uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font font <<= 8; font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font @@ -1704,8 +1856,8 @@ static void da2_render_textm3(da2_t* da2) if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) { //int cursorwidth = (da2->crtc[0x1f] & 0x20 ? 26 : 13); - //int cursorcolor = (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrregs[0x1a]) : 2;//Choose color 2 if mode 8 - //fg = (da2->attrregs[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; + //int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;//Choose color 2 if mode 8 + //fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; //bg = 0; //if (attr & 0x04) {//Color 0 if reverse // bg = fg; @@ -1876,9 +2028,9 @@ void da2_recalctimings(da2_t* da2) da2->clock = da2->da2const; - da2->lowres = da2->attrregs[LC_VERTICAL_SYNC_START] & 0x40; + //da2->lowres = da2->attrc[LV_MODE_CONTROL] & 0x40; - da2->interlace = 0; + //da2->interlace = 0; //da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b da2->ca_adj = 0; @@ -1888,8 +2040,8 @@ void da2_recalctimings(da2_t* da2) da2->hdisp_time = da2->hdisp; da2->render = da2_render_blank; //determine display mode - //if (da2->attr_palette_enable && (da2->attrregs[0x1f] & 0x08)) - if (da2->attrregs[LV_COMPATIBILITY] & 0x08) + //if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) + if (da2->attrc[LV_COMPATIBILITY] & 0x08) { if (!(da2->ioctl[LS_MODE] & 0x01)) {//16 color graphics mode da2->hdisp *= 16; @@ -1907,7 +2059,7 @@ void da2_recalctimings(da2_t* da2) } } else {//text mode - if (da2->attrregs[LV_ATTRIBUTE_CNTL] & 1) { + if (da2->attrc[LV_ATTRIBUTE_CNTL] & 1) { da2_log("Set videomode to PS/55 Mode 03 text.\n"); da2->render = da2_render_textm3; da2->vram_display_mask = DA2_MASK_CRAM; @@ -2118,7 +2270,7 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) return da2->mmio.ram[addr]; break; case 0x10://Font ROM - //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); + da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); if (addr > DA2_FONTROM_SIZE) return 0xff; return da2->mmio.font[addr]; break; @@ -2165,6 +2317,7 @@ static uint16_t da2_mmio_readw(uint32_t addr, void* p) for (int i = 0; i < 8; i++) da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read vram into latch +#ifdef ENABLE_DA2_DEBUGBLT ////debug //if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) //{ @@ -2179,7 +2332,7 @@ static uint16_t da2_mmio_readw(uint32_t addr, void* p) // fprintf(da2->mmrdbg_fp, "%X", pixeldata); //} //da2->mmrdbg_vidaddr = addr; - //// +#endif if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 uint16_t ret = 0; @@ -2200,7 +2353,7 @@ static uint16_t da2_mmio_readw(uint32_t addr, void* p) else { return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); } -} +} static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) { @@ -2231,12 +2384,15 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) break; case 0x00: //da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - addr &= 0x7f;//OS/2 write addr 1cf80-1cfc3, val xx - if (addr >= DA2_BLT_MEMSIZE) - { - da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - return; - } + //addr &= 0x7f;//OS/2 write addr 1cf80-1cfc3, val xx + //if (addr >= DA2_BLT_MEMSIZE) + //{ + // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + // return; + //} + da2->bitblt.indata = 1; + if(da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) + da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); da2->bitblt.payload[da2->bitblt.payload_addr] = val; da2->bitblt.payload_addr++; break; @@ -2249,23 +2405,25 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) { uint8_t wm = da2->writemask; //da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); +#ifdef ENABLE_DA2_DEBUGBLT //debug //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) //{ - //if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) - //{ - // fprintf(da2->mmdbg_fp, "\nB %x ", addr); - // for (int i = 0; i <= 0xb; i++) - // fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); - //} - //for (int i = 0; i < 8; i++) - //{ - // int pixeldata = 0; - // if (val & (1 << (7 - i))) pixeldata = (da2->writemask & 0xf); - // fprintf(da2->mmdbg_fp, "%X", pixeldata); - //} - //da2->mmdbg_vidaddr = addr; + if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) + { + fprintf(da2->mmdbg_fp, "\nB %x ", addr); + for (int i = 0; i <= 0xb; i++) + fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + } + for (int i = 0; i < 8; i++) + { + int pixeldata = 0; + if (val & (1 << (7 - i))) pixeldata = (da2->writemask & 0xf); + fprintf(da2->mmdbg_fp, "%X", pixeldata); + } + da2->mmdbg_vidaddr = addr; //} +#endif cycles -= video_timing_write_b; @@ -2273,7 +2431,7 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) addr <<= 3; for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch + da2->gdcsrc[i] = da2->gdcla[i];//use latch //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); @@ -2361,24 +2519,26 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; bitmask <<= 8; bitmask |= (uint16_t)da2->gdcreg[LG_BIT_MASK_LOW]; +#ifdef ENABLE_DA2_DEBUGBLT //debug //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) //{ - //if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) - //{ - // fprintf(da2->mmdbg_fp, "\nW %x ", addr); - // for (int i = 0; i <= 0xb; i++) - // fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); - //} - //for (int i = 0; i < 16; i++) - //{ - // int pixeldata = 0; - // if (val & (1 << (15 - i))) pixeldata = (da2->writemask & 0xf); - // fprintf(da2->mmdbg_fp, "%X", pixeldata); - //} - //da2->mmdbg_vidaddr = addr; + if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) + { + fprintf(da2->mmdbg_fp, "\nW %x ", addr); + for (int i = 0; i <= 0xb; i++) + fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + } + for (int i = 0; i < 16; i++) + { + int pixeldata = 0; + if (val & (1 << (15 - i))) pixeldata = (da2->writemask & 0xf); + fprintf(da2->mmdbg_fp, "%X", pixeldata); + } + da2->mmdbg_vidaddr = addr; //} - //cycles -= video_timing_write_w; +#endif + cycles -= video_timing_write_w; //cycles_lost += video_timing_write_w; //da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); @@ -2585,8 +2745,8 @@ void da2_poll(void* priv) //da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); da2->displine++; - if (da2->interlace) - da2->displine++; + //if (da2->interlace) + // da2->displine++; if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) { //da2_log("Vsync off at line %i\n",displine); @@ -2641,7 +2801,7 @@ void da2_poll(void* priv) //if (da2->crtc[10] & 0x20) da2->cursoron = 0; //else da2->cursoron = da2->blink & 16; if (da2->ioctl[LS_MODE] & 1) {//in text mode - if (da2->attrregs[LV_CURSOR_CONTROL] & 0x01)//cursor blinking + if (da2->attrc[LV_CURSOR_CONTROL] & 0x01)//cursor blinking { da2->cursoron = (da2->blink | 1) & da2->blinkconf; } @@ -2673,8 +2833,8 @@ void da2_poll(void* priv) da2->cgastat |= 8; x = da2->hdisp; - if (da2->interlace && !da2->oddeven) da2->lastline++; - if (da2->interlace && da2->oddeven) da2->firstline--; + //if (da2->interlace && !da2->oddeven) da2->lastline++; + //if (da2->interlace && da2->oddeven) da2->firstline--; wx = x; wy = da2->lastline - da2->firstline; @@ -2695,8 +2855,8 @@ void da2_poll(void* priv) //if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch + (da2->rowoffset << 1) + ((da2->crtc[5] & 0x60) >> 5); //else da2->ma = da2->maback = da2->ma_latch + ((da2->crtc[5] & 0x60) >> 5); //da2->ca = ((da2->crtc[0xe] << 8) | da2->crtc[0xf]) + ((da2->crtc[0xb] & 0x60) >> 5) + da2->ca_adj; - if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch; - else da2->ma = da2->maback = da2->ma_latch; +/* if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch; + else*/ da2->ma = da2->maback = da2->ma_latch; da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj; da2->ma <<= 1; @@ -2715,7 +2875,7 @@ void da2_poll(void* priv) da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; da2->dispon = 1; da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; - da2->scrollcache = da2->attrregs[LV_PANNING] & 7; + da2->scrollcache = da2->attrc[LV_PANNING] & 7; } if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) da2->con = 1; @@ -2793,12 +2953,12 @@ da2_reset(void* priv) da2->ioctl[LS_CONFIG2] = Mon_ID1; /* Configuration (High): Monitor ID 0-2 */ da2->fctl[0] = 0x2b; /* 3E3h:0 */ da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ - da2->attrregs[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ + da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ da2->ma_latch = 0; da2->interlace = 0; - da2->attrregs[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ + da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ da2->attr_palette_enable = 0; /* disable attribute generator */ /* Set default color palette (Display driver of Win 3.1 won't reset palette) */ @@ -2889,7 +3049,7 @@ void da2_close(void *p) } f = fopen("da2_attrpal.dmp", "wb"); if (f != NULL) { - fwrite(da2->attrregs, 32, 1, f); + fwrite(da2->attrc, 32, 1, f); fclose(f); } f = fopen("da2_dacrgb.dmp", "wb"); @@ -2906,7 +3066,7 @@ void da2_close(void *p) for (int i = 0; i < 0x20; i++) fprintf(f, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); for (int i = 0; i < 0x40; i++) - fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrregs[i]); + fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrc[i]); for (int i = 0; i < 0x10; i++) fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); for (int i = 0; i < 0x10; i++) @@ -2939,7 +3099,7 @@ void da2_close(void *p) } if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); - free(da2->bitblt.debug_reg); + free(da2->bitblt.debug_reg); #endif free(da2->cram); free(da2->vram); From f3016bc93eb3361cc389a30be71cd274da5382e7 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Mon, 13 Jan 2025 22:48:44 +0700 Subject: [PATCH 19/82] Added onboard sound to 4 machines --- src/machine/m_at_socket7.c | 4 ++++ src/machine/m_at_socket7_3v.c | 4 ++++ src/machine/m_at_socket8.c | 8 ++++++++ src/machine/machine_table.c | 8 ++++---- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index f80d2d421..52b16c212 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -849,6 +849,10 @@ machine_at_gw2kte_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + + if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)->available()) + machine_snd = device_add(machine_get_snd_device(machine)); + device_add(&i430vx_device); device_add(&piix3_device); device_add(&fdc37c932fr_device); diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 40ae221a0..4b980f2b0 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -694,6 +694,10 @@ machine_at_gw2kma_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + + if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)->available()) + machine_snd = device_add(machine_get_snd_device(machine)); + device_add(&i430vx_device); device_add(&piix3_device); device_add(&fdc37c932fr_device); diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index e6f78f6a2..59c412447 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -249,6 +249,10 @@ machine_at_vs440fx_init(const machine_t *model) pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(machine_get_snd_device(machine)); + device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_intel_ami_pci_device); @@ -283,6 +287,10 @@ machine_at_gw2kvenus_init(const machine_t *model) pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(machine_get_snd_device(machine)); + device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_intel_ami_pci_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 330b7d52a..b9ee8af40 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -13989,7 +13989,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -14004,7 +14004,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &cs4236b_device, .net_device = NULL }, /* Has the AMIKey-2 (updated 'H') KBC firmware. */ @@ -14113,7 +14113,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -14128,7 +14128,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &cs4236b_device, .net_device = NULL }, /* Has the AMIKey-2 (updated 'H') KBC firmware. */ From a7472005ba746d9522e8b45657bd728f72577edb Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Mon, 13 Jan 2025 23:00:29 +0700 Subject: [PATCH 20/82] Added Maxtium Computer SmartBX --- src/include/86box/machine.h | 1 + src/machine/m_at_socket370.c | 32 ++++++++++++++++++++++++++++ src/machine/machine_table.c | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 0cd3564ee..6edcb6ac4 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -839,6 +839,7 @@ extern int machine_at_atc7020bxii_init(const machine_t *); extern int machine_at_m773_init(const machine_t *); extern int machine_at_ambx133_init(const machine_t *); extern int machine_at_awo671r_init(const machine_t *); +extern int machine_at_smartbx_init(const machine_t *); extern int machine_at_63a1_init(const machine_t *); extern int machine_at_s370sba_init(const machine_t *); extern int machine_at_apas3_init(const machine_t *); diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 9be2d45b8..3513859cb 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -402,6 +402,38 @@ machine_at_awo671r_init(const machine_t *model) return ret; } +int +machine_at_smartbx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/smartbx/sbx107.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4e_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&w83977ef_device); + device_add(&sst_flash_39sf020_device); + spd_register(SPD_TYPE_SDRAM, 0x7, 256); + + return ret; +} + int machine_at_63a1_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index b9ee8af40..d3dcd47f4 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -15758,6 +15758,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC + firmware. */ + { + .name = "[i440BX] Maxtium Computer SmartBX", + .internal_name = "smartbx", + .type = MACHINE_TYPE_SOCKET370, + .chipset = MACHINE_CHIPSET_INTEL_440BX, + .init = machine_at_smartbx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET370, + .block = CPU_BLOCK_NONE, + .min_bus = 66666667, + .max_bus = 100000000, + .min_voltage = 1300, + .max_voltage = 3500, + .min_multi = 1.5, + .max_multi = 8.0 + }, + .bus_flags = MACHINE_PS2_A97 | MACHINE_BUS_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, + .ram = { + .min = 8192, + .max = 393216, + .step = 8192 + }, + .nvrmask = 255, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 440ZX */ /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC From 49aa0edd2256a5adcad2cace7067281bf5f1b951 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Mon, 13 Jan 2025 23:14:11 +0700 Subject: [PATCH 21/82] Added Dell Dimension X30 --- src/include/86box/machine.h | 1 + src/machine/m_at_386dx_486.c | 22 ++++++++++++++++++++ src/machine/machine_table.c | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 6edcb6ac4..4e4b2e558 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -519,6 +519,7 @@ extern int machine_at_cs4031_init(const machine_t *); extern int machine_at_pb410a_init(const machine_t *); extern int machine_at_decpclpv_init(const machine_t *); +extern int machine_at_dellx30_init(const machine_t *); extern int machine_at_acerv10_init(const machine_t *); extern int machine_at_acera1g_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index d3c7a21d2..dbe91de51 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -482,6 +482,28 @@ machine_at_decpclpv_init(const machine_t *model) return ret; } +int +machine_at_dellx30_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/dellx30/shk2a03.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&sis_85c461_device); + device_add(&keyboard_ps2_acer_pci_device); + device_add(&fdc37c665_ide_device); + device_add(&ide_opti611_vlb_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + static void machine_at_ali1429_common_init(const machine_t *model, int is_green) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index d3dcd47f4..75198b3e3 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6936,6 +6936,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has FDC37C665 SIO with OPTi 82c611 IDE onboard */ + { + .name = "[SiS 461] Dell Dimension X30", + .internal_name = "dellx30", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_461, /* Chipset relabeled as Micronics MIC 471 */ + .init = machine_at_dellx30_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .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_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The BIOS string ends in -U, unless command 0xA1 (AMIKey get version) returns an 'F', in which case, it ends in -F, so it has an AMIKey F KBC firmware. The photo of the board shows an AMIKey KBC which is indeed F. */ From 3b4d6d1f9e708b3599c756c33db238ab33021a7b Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Mon, 13 Jan 2025 23:33:20 +0700 Subject: [PATCH 22/82] Forgotten one change --- src/machine/machine_table.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 75198b3e3..cac50fbcf 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11240,7 +11240,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -11255,7 +11255,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &sb_vibra16c_onboard_device, .net_device = NULL }, @@ -12263,7 +12263,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -12278,7 +12278,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &sb_vibra16c_onboard_device, .net_device = NULL }, /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix From c924a60be7abb1b74644fb7fb375632fc375824f Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Tue, 14 Jan 2025 00:06:25 +0700 Subject: [PATCH 23/82] Removed flash device from X30 Fixes BootBlock error --- src/machine/m_at_386dx_486.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index dbe91de51..28e5c8549 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -499,7 +499,6 @@ machine_at_dellx30_init(const machine_t *model) device_add(&keyboard_ps2_acer_pci_device); device_add(&fdc37c665_ide_device); device_add(&ide_opti611_vlb_device); - device_add(&intel_flash_bxt_device); return ret; } From b002fed6023890e0056ea5e54aff74260547938a Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Tue, 14 Jan 2025 00:13:54 +0700 Subject: [PATCH 24/82] Removed non-working SmartBX --- src/include/86box/machine.h | 1 - src/machine/m_at_socket370.c | 32 ---------------------------- src/machine/machine_table.c | 41 ------------------------------------ 3 files changed, 74 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 4e4b2e558..48e9be1c3 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -840,7 +840,6 @@ extern int machine_at_atc7020bxii_init(const machine_t *); extern int machine_at_m773_init(const machine_t *); extern int machine_at_ambx133_init(const machine_t *); extern int machine_at_awo671r_init(const machine_t *); -extern int machine_at_smartbx_init(const machine_t *); extern int machine_at_63a1_init(const machine_t *); extern int machine_at_s370sba_init(const machine_t *); extern int machine_at_apas3_init(const machine_t *); diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 3513859cb..9be2d45b8 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -402,38 +402,6 @@ machine_at_awo671r_init(const machine_t *model) return ret; } -int -machine_at_smartbx_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/smartbx/sbx107.bin", - 0x000c0000, 262144, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init_ex(model, 2); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); - device_add(&i440bx_device); - device_add(&piix4e_device); - device_add(&keyboard_ps2_ami_pci_device); - device_add(&w83977ef_device); - device_add(&sst_flash_39sf020_device); - spd_register(SPD_TYPE_SDRAM, 0x7, 256); - - return ret; -} - int machine_at_63a1_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index cac50fbcf..1aeb28526 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -15798,47 +15798,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC - firmware. */ - { - .name = "[i440BX] Maxtium Computer SmartBX", - .internal_name = "smartbx", - .type = MACHINE_TYPE_SOCKET370, - .chipset = MACHINE_CHIPSET_INTEL_440BX, - .init = machine_at_smartbx_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET370, - .block = CPU_BLOCK_NONE, - .min_bus = 66666667, - .max_bus = 100000000, - .min_voltage = 1300, - .max_voltage = 3500, - .min_multi = 1.5, - .max_multi = 8.0 - }, - .bus_flags = MACHINE_PS2_A97 | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, - .ram = { - .min = 8192, - .max = 393216, - .step = 8192 - }, - .nvrmask = 255, - .kbc_device = NULL, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = NULL, - .fdc_device = NULL, - .sio_device = NULL, - .vid_device = NULL, - .snd_device = NULL, - .net_device = NULL - }, /* 440ZX */ /* Has a Winbond W83977TF Super I/O chip with on-chip KBC with AMIKey-2 KBC From ffe6af94cfaa48e16cd6e5921705b58091fc6790 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Tue, 14 Jan 2025 00:26:05 +0700 Subject: [PATCH 25/82] Removed non-working X30 --- src/include/86box/machine.h | 1 - src/machine/m_at_386dx_486.c | 21 ------------------- src/machine/machine_table.c | 40 ------------------------------------ 3 files changed, 62 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 48e9be1c3..0cd3564ee 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -519,7 +519,6 @@ extern int machine_at_cs4031_init(const machine_t *); extern int machine_at_pb410a_init(const machine_t *); extern int machine_at_decpclpv_init(const machine_t *); -extern int machine_at_dellx30_init(const machine_t *); extern int machine_at_acerv10_init(const machine_t *); extern int machine_at_acera1g_init(const machine_t *); diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 28e5c8549..d3c7a21d2 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -482,27 +482,6 @@ machine_at_decpclpv_init(const machine_t *model) return ret; } -int -machine_at_dellx30_init(const machine_t *model) -{ - int ret; - - ret = bios_load_linear("roms/machines/dellx30/shk2a03.bin", - 0x000e0000, 131072, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_init(model); - - device_add(&sis_85c461_device); - device_add(&keyboard_ps2_acer_pci_device); - device_add(&fdc37c665_ide_device); - device_add(&ide_opti611_vlb_device); - - return ret; -} - static void machine_at_ali1429_common_init(const machine_t *model, int is_green) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 1aeb28526..baba2723c 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -6936,46 +6936,6 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has FDC37C665 SIO with OPTi 82c611 IDE onboard */ - { - .name = "[SiS 461] Dell Dimension X30", - .internal_name = "dellx30", - .type = MACHINE_TYPE_486_S3, - .chipset = MACHINE_CHIPSET_SIS_461, /* Chipset relabeled as Micronics MIC 471 */ - .init = machine_at_dellx30_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET3, - .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_VLB, - .flags = MACHINE_IDE | MACHINE_APM, - .ram = { - .min = 1024, - .max = 65536, - .step = 1024 - }, - .nvrmask = 127, - .kbc_device = NULL, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = NULL, - .fdc_device = NULL, - .sio_device = NULL, - .vid_device = NULL, - .snd_device = NULL, - .net_device = NULL - }, /* The BIOS string ends in -U, unless command 0xA1 (AMIKey get version) returns an 'F', in which case, it ends in -F, so it has an AMIKey F KBC firmware. The photo of the board shows an AMIKey KBC which is indeed F. */ From 9b7d5198d7f80e955756522079b642a8137c4aa1 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Sat, 18 Jan 2025 04:14:23 +0700 Subject: [PATCH 26/82] Removed onboard sound from three machines Per richardg867 --- src/machine/m_at_socket7_3v.c | 3 --- src/machine/m_at_socket8.c | 6 ------ src/machine/machine_table.c | 12 ++++++------ 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 4b980f2b0..262169010 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -695,9 +695,6 @@ machine_at_gw2kma_init(const machine_t *model) pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); - if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)->available()) - machine_snd = device_add(machine_get_snd_device(machine)); - device_add(&i430vx_device); device_add(&piix3_device); device_add(&fdc37c932fr_device); diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 59c412447..6d4776637 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -250,9 +250,6 @@ machine_at_vs440fx_init(const machine_t *model) pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - if (sound_card_current[0] == SOUND_INTERNAL) - device_add(machine_get_snd_device(machine)); - device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_intel_ami_pci_device); @@ -288,9 +285,6 @@ machine_at_gw2kvenus_init(const machine_t *model) pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - if (sound_card_current[0] == SOUND_INTERNAL) - device_add(machine_get_snd_device(machine)); - device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_intel_ami_pci_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index baba2723c..bd31a58b1 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11200,7 +11200,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -11215,7 +11215,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = &sb_vibra16c_onboard_device, + .snd_device = NULL, .net_device = NULL }, @@ -13989,7 +13989,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -14004,7 +14004,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = &cs4236b_device, + .snd_device = NULL, .net_device = NULL }, /* Has the AMIKey-2 (updated 'H') KBC firmware. */ @@ -14113,7 +14113,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 524288, @@ -14128,7 +14128,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = &cs4236b_device, + .snd_device = NULL, .net_device = NULL }, /* Has the AMIKey-2 (updated 'H') KBC firmware. */ From c20c211e29c1150bb88076221b72075be7509af2 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Sat, 18 Jan 2025 04:17:27 +0700 Subject: [PATCH 27/82] Line fixes --- src/machine/m_at_socket7_3v.c | 1 - src/machine/m_at_socket8.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 262169010..40ae221a0 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -694,7 +694,6 @@ machine_at_gw2kma_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); - device_add(&i430vx_device); device_add(&piix3_device); device_add(&fdc37c932fr_device); diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 6d4776637..e6f78f6a2 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -249,7 +249,6 @@ machine_at_vs440fx_init(const machine_t *model) pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_intel_ami_pci_device); @@ -284,7 +283,6 @@ machine_at_gw2kvenus_init(const machine_t *model) pci_register_slot(0x11, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_intel_ami_pci_device); From f89d960b7e499d1544b9301e30e7dec222e58ff4 Mon Sep 17 00:00:00 2001 From: MaxwellS04 Date: Sat, 18 Jan 2025 04:29:05 +0700 Subject: [PATCH 28/82] Added back onboard sound to Mailman Per richardg867 --- src/machine/m_at_socket7_3v.c | 4 ++++ src/machine/machine_table.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 40ae221a0..4b980f2b0 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -694,6 +694,10 @@ machine_at_gw2kma_init(const machine_t *model) pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); + + if ((sound_card_current[0] == SOUND_INTERNAL) && machine_get_snd_device(machine)->available()) + machine_snd = device_add(machine_get_snd_device(machine)); + device_add(&i430vx_device); device_add(&piix3_device); device_add(&fdc37c932fr_device); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index bd31a58b1..7b0de9805 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11200,7 +11200,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 131072, @@ -11215,7 +11215,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &sb_vibra16c_onboard_device, .net_device = NULL }, From 23ba9889d26c62270bf254e8d75e97eb445ea3ac Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 20 Jan 2025 15:16:36 +0900 Subject: [PATCH 29/82] Fixed an illegal memory access error Fixed an illegal memory access error when reading font ROM data beyond 1 MB border --- src/video/vid_ps55da2.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 6a90a3dc3..d75d0aa03 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -42,6 +42,7 @@ #define DA2_FONTROM_BASESBCS 0x98000 #define DA2_GAIJIRAM_SBCS 0x34000 #define DA2_GAIJIRAM_SBEX 0x3c000 +#define DA2_INVALIDACCESS8 0xff #define DA2_MASK_MMIO 0x1ffff #define DA2_MASK_GRAM 0x1ffff #define DA2_MASK_CRAM 0xfff @@ -1244,7 +1245,7 @@ uint16_t da2_in(uint16_t addr, void *p) break; case LS_DATA: //da2->ioctl[3] = 0x80;//3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) - if (da2->ioctladdr > 0xf) return 0xff; + if (da2->ioctladdr > 0xf) return DA2_INVALIDACCESS8; temp = da2->ioctl[da2->ioctladdr]; if (da2->ioctladdr == LS_STATUS) { /* Status register */ if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 0x50 && da2->attrc[LV_COMPATIBILITY] & 0x08) @@ -1275,14 +1276,14 @@ uint16_t da2_in(uint16_t addr, void *p) temp = da2->fctladdr; break; case LF_DATA: - if (da2->fctladdr > 0x1f) return 0xff; + if (da2->fctladdr > 0x1f) return DA2_INVALIDACCESS8; temp = da2->fctl[da2->fctladdr]; break; case LC_INDEX: temp = da2->crtcaddr; break; case LC_DATA: - if (da2->crtcaddr > 0x1f) return 0xff; + if (da2->crtcaddr > 0x1f) return DA2_INVALIDACCESS8; temp = da2->crtc[da2->crtcaddr]; break; case LV_PORT: @@ -2270,12 +2271,12 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) return da2->mmio.ram[addr]; break; case 0x10://Font ROM + if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); - if (addr > DA2_FONTROM_SIZE) return 0xff; return da2->mmio.font[addr]; break; default: - return 0xff;//invalid memory access + return DA2_INVALIDACCESS8;//invalid memory access break; } } @@ -2677,7 +2678,7 @@ static void da2_code_writew(uint32_t addr, uint16_t val, void* p) static uint8_t da2_code_read(uint32_t addr, void* p) { da2_t* da2 = (da2_t*)p; - if ((addr & ~DA2_MASK_CRAM) != 0xE0000) return 0xff; + if ((addr & ~DA2_MASK_CRAM) != 0xE0000) return DA2_INVALIDACCESS8; addr &= DA2_MASK_CRAM; return da2->cram[addr]; } From 6614a83b340527263aa9e8312b61d41cb71626d9 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 4 Feb 2025 20:28:24 +0900 Subject: [PATCH 30/82] correct font read address in PS/55 video mode 03 --- src/video/vid_ps55da2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index d75d0aa03..f3b7c7834 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1830,7 +1830,7 @@ static void da2_render_textm3(da2_t* da2) else { // the char code is SBCS (ANK) uint32_t fontbase; - fontbase = DA2_FONTROM_BASESBCS; + fontbase = DA2_GAIJIRAM_SBCS; uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font font <<= 8; font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font From f12b975ebacd8e33cf0c5c29f1e0e984abbb028b Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 6 Feb 2025 13:15:18 +0900 Subject: [PATCH 31/82] Added support for PS/55 DA Simplified Chinese font Changed a file path for the PS/55 DA Japanese font ROM. --- src/qt/qt_settingsdisplay.cpp | 13 +++++++ src/qt/qt_settingsdisplay.hpp | 2 + src/qt/qt_settingsdisplay.ui | 9 ++++- src/video/vid_ps55da2.c | 73 ++++++++++++++++++++++++++++------- 4 files changed, 82 insertions(+), 15 deletions(-) diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index 42617c4be..f6be74cf2 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -139,6 +139,12 @@ SettingsDisplay::on_pushButtonConfigureXga_clicked() } } +void +SettingsDisplay::on_pushButtonConfigureDa2_clicked() +{ + DeviceConfig::ConfigureDevice(&ps55da2_device, 0, qobject_cast(Settings::settings)); +} + void SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) { @@ -176,6 +182,7 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) ui->checkBoxDa2->setChecked(da2_standalone_enabled && machineSupportsDa2); ui->pushButtonConfigureXga->setEnabled(ui->checkBoxXga->isEnabled() && ui->checkBoxXga->isChecked()); + ui->pushButtonConfigureDa2->setEnabled(ui->checkBoxDa2->isEnabled() && ui->checkBoxDa2->isChecked()); int c = 2; @@ -250,6 +257,12 @@ SettingsDisplay::on_checkBoxXga_stateChanged(int state) ui->pushButtonConfigureXga->setEnabled(state == Qt::Checked); } +void +SettingsDisplay::on_checkBoxDa2_stateChanged(int state) +{ + ui->pushButtonConfigureDa2->setEnabled(state == Qt::Checked); +} + void SettingsDisplay::on_comboBoxVideoSecondary_currentIndexChanged(int index) { diff --git a/src/qt/qt_settingsdisplay.hpp b/src/qt/qt_settingsdisplay.hpp index 6297f7eae..f2edb0c8a 100644 --- a/src/qt/qt_settingsdisplay.hpp +++ b/src/qt/qt_settingsdisplay.hpp @@ -30,9 +30,11 @@ private slots: private slots: void on_checkBoxVoodoo_stateChanged(int state); void on_checkBoxXga_stateChanged(int state); + void on_checkBoxDa2_stateChanged(int state); void on_comboBoxVideo_currentIndexChanged(int index); void on_pushButtonConfigureVoodoo_clicked(); void on_pushButtonConfigureXga_clicked(); + void on_pushButtonConfigureDa2_clicked(); void on_pushButtonConfigure_clicked(); private: diff --git a/src/qt/qt_settingsdisplay.ui b/src/qt/qt_settingsdisplay.ui index e3e081848..8be84a17f 100644 --- a/src/qt/qt_settingsdisplay.ui +++ b/src/qt/qt_settingsdisplay.ui @@ -113,13 +113,20 @@ - + IBM PS/55 Display Adapter Graphics + + + + Configure + + + diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index f3b7c7834..a6d55c76a 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -37,8 +37,9 @@ #include <86box/vid_svga_render.h> #include "cpu.h" -#define DA2_FONTROM_PATH "roms/video/da2/PS55FNTJ.BIN" -#define DA2_FONTROM_SIZE 1024*1024 +#define DA2_FONTROM_PATH_JPAN "roms/video/da2/94X1320.BIN" +#define DA2_FONTROM_PATH_HANT "roms/video/da2/23F2698.BIN" +#define DA2_FONTROM_SIZE 1536*1024 #define DA2_FONTROM_BASESBCS 0x98000 #define DA2_GAIJIRAM_SBCS 0x34000 #define DA2_GAIJIRAM_SBEX 0x3c000 @@ -54,6 +55,10 @@ #define DA2_DEBUG_BLTLOG_MAX 256*1024 #define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe #define DA2_DEBUG_BLT_USEDRESET 0xfefefe +#define DA2_DCONFIG_FONT_JPAN 0 /* for Code page 932 Japanese */ +//#define DA2_DCONFIG_FONT_HANG 1 /* for Code page 934 Hangul */ +//#define DA2_DCONFIG_FONT_HANS 2 /* for Code page 936 Simplified Chinese */ +#define DA2_DCONFIG_FONT_HANT 3 /* for Code page 938 Traditional Chinese */ #define DA2_BLT_CIDLE 0 #define DA2_BLT_CFILLRECT 1 @@ -100,7 +105,12 @@ #define OldLSI 0x20 /* DA-2 or DA-3,5 */ #define Mon_ID3 0x10 #define FontCard 0x08 /* ? */ -/* IO 3E0/3E1:0Ah Hardware Configuration Value H (imported from OS/2 DDK) */ +/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ +#define Page_One 0x06 /* 80000h 110b */ +#define Page_Two 0x05 /* 100000h 101b */ +#define Page_Four 0x03 /* 200000h 011b */ + +/* IO 3E0/3E1:0Bh Hardware Configuration Value H (imported from OS/2 DDK) */ #define AddPage 0x08 /* ? */ #define Mon_ID2 0x04 #define Mon_ID1 0x02 @@ -110,10 +120,6 @@ //#define StarbuckM 0x09 //1001b x grayscale //#define Lark_B 0x02 //0010b IBM 9517 color 1040x768 //#define Dallas 0x0B //1011b IBM 8515, 9515 color 1040x740 B palette -/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ -#define Page_One 0x06 /* 80000h 110b */ -#define Page_Two 0x05 /* 100000h 101b */ -#define Page_Four 0x03 /* 200000h 011b */ /* DA2 Registers (imported from OS/2 DDK) */ #define AC_REG 0x3EE @@ -1045,6 +1051,8 @@ void da2_out(uint16_t addr, uint16_t val, void *p) case LF_DATA: //da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); if (da2->fctladdr > 0x1f) return; + if (da2->fctl[da2->fctladdr & 0x1f] != val) + da2_log("fctl changed %x: %x -> %x %04X:%04X\n", da2->fctladdr & 0x1f, da2->fctl[da2->fctladdr & 0x1f], val, cs >> 4, cpu_state.pc); oldval = da2->fctl[da2->fctladdr]; da2->fctl[da2->fctladdr] = val; if (da2->fctladdr == 0 && oldval != val) @@ -1547,7 +1555,7 @@ Bank 5 (B9580-?;IBMJ 2930-295e?) : Full-width box drawing characters - The signature 80h, 01h must be placed at Bank 0:1AFFEh to run OS/2 J1.3. + Some models have the signature 80h, 01h placed at Bank 0:1AFFEh. (it disables hardware text drawing in OS/2 J1.3) [Gaiji RAM Map (DA2)] Bank 0 00000-1FFFFh placed between A0000h-BFFFFh @@ -2271,8 +2279,9 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) return da2->mmio.ram[addr]; break; case 0x10://Font ROM + //if (addr >= 0x180000) addr -= 0x40000; if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; - da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); + //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); return da2->mmio.font[addr]; break; default: @@ -2307,7 +2316,7 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) static uint16_t da2_mmio_readw(uint32_t addr, void* p) { da2_t* da2 = (da2_t*)p; - //da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); if (da2->ioctl[LS_MMIO] & 0x10) { return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); } @@ -2962,7 +2971,7 @@ da2_reset(void* priv) da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ da2->attr_palette_enable = 0; /* disable attribute generator */ - /* Set default color palette (Display driver of Win 3.1 won't reset palette) */ + /* Set default color palette (Windows 3.1 display driver won't reset palette) */ da2_out(0x3c8, 0, da2); for (int i = 0; i < 256; i++) { da2_out(0x3c9, ps55_palette_color[i & 0x3F][0], da2); @@ -2991,7 +3000,17 @@ static void *da2_init() da2->cram = malloc(0x1000); da2->vram_display_mask = DA2_MASK_CRAM; da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h - da2_loadfont(DA2_FONTROM_PATH, da2); + + int fonttype = device_get_config_int("font"); + switch(fonttype) + { + case DA2_DCONFIG_FONT_HANT: + da2_loadfont(DA2_FONTROM_PATH_HANT, da2); + break; + case DA2_DCONFIG_FONT_JPAN: + da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); + break; + } mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); @@ -3023,7 +3042,7 @@ static void *da2_init() } static int da2_available() { - return rom_present(DA2_FONTROM_PATH); + return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); } void da2_close(void *p) @@ -3122,6 +3141,32 @@ void da2_force_redraw(void *p) da2->fullchange = changeframecount; } +static const device_config_t da2_configuration[] = { + // clang-format off + { + .name = "font", + .description = "Font", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "CP932 (Japanese)", + .value = DA2_DCONFIG_FONT_JPAN + }, + { + .description = "CP938 (Traditional Chinese)", + .value = DA2_DCONFIG_FONT_HANT + }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + const device_t ps55da2_device = { .name = "IBM Display Adapter II (MCA)", .internal_name = "ps55da2", @@ -3133,7 +3178,7 @@ const device_t ps55da2_device = { { .available = da2_available }, .speed_changed = da2_speed_changed, .force_redraw = da2_force_redraw, - .config = NULL + .config = da2_configuration }; void From 3bfd2a6b16e19f598ef00dbd2884e5cbc1285fe3 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 6 Feb 2025 17:20:58 +0900 Subject: [PATCH 32/82] Added a configuration to switch monitor types --- src/video/vid_ps55da2.c | 78 +++++++++++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index a6d55c76a..6d4f43ca6 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -59,6 +59,8 @@ //#define DA2_DCONFIG_FONT_HANG 1 /* for Code page 934 Hangul */ //#define DA2_DCONFIG_FONT_HANS 2 /* for Code page 936 Simplified Chinese */ #define DA2_DCONFIG_FONT_HANT 3 /* for Code page 938 Traditional Chinese */ +#define DA2_DCONFIG_MONTYPE_COLOR 0x0A +#define DA2_DCONFIG_MONTYPE_MONO 0x09 #define DA2_BLT_CIDLE 0 #define DA2_BLT_CFILLRECT 1 @@ -102,8 +104,10 @@ | EFD8h | Display Adapter /J | | | X | X | X | */ /* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ +//2501 +//2500 mono #define OldLSI 0x20 /* DA-2 or DA-3,5 */ -#define Mon_ID3 0x10 +//#define Mon_ID3 0x10 #define FontCard 0x08 /* ? */ /* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ #define Page_One 0x06 /* 80000h 110b */ @@ -112,14 +116,14 @@ /* IO 3E0/3E1:0Bh Hardware Configuration Value H (imported from OS/2 DDK) */ #define AddPage 0x08 /* ? */ -#define Mon_ID2 0x04 -#define Mon_ID1 0x02 -#define Mon_ID0 0x01 +//#define Mon_ID2 0x04 +//#define Mon_ID1 0x02 +//#define Mon_ID0 0x01 /* Monitor ID (imported from OS/2 DDK 1.2) */ -//#define StarbuckC 0x0A //1010b IBM 8514, 9518 color 1040x768 -//#define StarbuckM 0x09 //1001b x grayscale -//#define Lark_B 0x02 //0010b IBM 9517 color 1040x768 -//#define Dallas 0x0B //1011b IBM 8515, 9515 color 1040x740 B palette +//#define StarbuckC 0x0A //1 010b IBM 8514, 9518 color 1040x768 +//#define StarbuckM 0x09 //1 001b IBM 8507, 8604 grayscale +//#define Lark_B 0x02 //0 010b IBM 9517 color 1040x768 but 4pp +//#define Dallas 0x0B //1 011b IBM 8515, 9515 color 1040x740 B palette /* DA2 Registers (imported from OS/2 DDK) */ #define AC_REG 0x3EE @@ -400,8 +404,7 @@ typedef struct da2_t uint8_t pos_regs[8]; svga_t *mb_vga; - - //int vidsys_ena; + uint8_t monitorid; int old_pos2; } da2_t; @@ -1256,12 +1259,25 @@ uint16_t da2_in(uint16_t addr, void *p) if (da2->ioctladdr > 0xf) return DA2_INVALIDACCESS8; temp = da2->ioctl[da2->ioctladdr]; if (da2->ioctladdr == LS_STATUS) { /* Status register */ - if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 0x50 && da2->attrc[LV_COMPATIBILITY] & 0x08) - temp &= 0x7F; /* Inactive when the RGB output voltage is high(or the cable is not connected to the color monitor). */ - else - temp |= 0x80; /* Active when the RGB output voltage is lowand the cable is connected to the color monitor. - If the cable or the monitor is wrong, it becomes inactive. */ - temp &= 0xf6;//idle + if (da2->attrc[LV_COMPATIBILITY] & 0x08) { /* for detecting monitor type and cable wiring */ + if (da2->monitorid == DA2_DCONFIG_MONTYPE_MONO) { + /* grayscale monitor */ + if ((da2->vgapal[0].r >= 10) || (da2->vgapal[0].g >= 40) || (da2->vgapal[0].b >= 10)) + temp &= 0x7F; /* Inactive when the RGB output voltage is high (or the cable is not connected to a color monitor). */ + else + temp |= 0x80; /* Active when the RGB output voltage is low and the cable is connected to a color monitor. + If the cable or the monitor is wrong, it becomes inactive. */ + } else { + /* color monitor */ + if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 80) + temp &= 0x7F; + else + temp |= 0x80; + } + } else { + temp |= 0x80; + } + temp &= 0xf6;//clear busy bits if (da2->bitblt.indata) /* for OS/2 J1.3 */ da2_bitblt_dopayload(da2); if (da2->bitblt.exec != DA2_BLT_CIDLE) @@ -2959,8 +2975,9 @@ da2_reset(void* priv) da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ - da2->ioctl[LS_CONFIG1] = OldLSI | Mon_ID3 | Page_Two; /* Configuration(Low) : DA - 2, Monitor ID 3, 1024 KB */ - da2->ioctl[LS_CONFIG2] = Mon_ID1; /* Configuration (High): Monitor ID 0-2 */ + da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA - 2, 1024 KB */ + da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8 ) << 2); /* Configuration 1 : Monitor ID 3 */ + da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ da2->fctl[0] = 0x2b; /* 3E3h:0 */ da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ @@ -3000,6 +3017,7 @@ static void *da2_init() da2->cram = malloc(0x1000); da2->vram_display_mask = DA2_MASK_CRAM; da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h + da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ int fonttype = device_get_config_int("font"); switch(fonttype) @@ -3145,12 +3163,9 @@ static const device_config_t da2_configuration[] = { // clang-format off { .name = "font", - .description = "Font", + .description = "Charset", .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 0, - .file_filter = "", - .spinner = { 0 }, + .default_int = DA2_DCONFIG_FONT_JPAN, .selection = { { .description = "CP932 (Japanese)", @@ -3163,6 +3178,23 @@ static const device_config_t da2_configuration[] = { { .description = "" } } }, + { + .name = "montype", + .description = "Monitor type", + .type = CONFIG_SELECTION, + .default_int = DA2_DCONFIG_MONTYPE_COLOR, + .selection = { + { + .description = "Color", + .value = DA2_DCONFIG_MONTYPE_COLOR + }, + { + .description = "Grayscale", + .value = DA2_DCONFIG_MONTYPE_MONO + }, + { .description = "" } + } + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; From cdc381b6192dca8c1e3a0be3607d72b28eba743e Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 11 Feb 2025 11:27:41 +0900 Subject: [PATCH 33/82] Added a new machine: IBM PS/55 model 5551-V0,V1 --- src/machine/m_ps2_mca.c | 174 +++++++++++++++++++++++++++++++++++- src/machine/machine_table.c | 40 +++++++++ src/video/vid_ps55da2.c | 44 ++++----- 3 files changed, 231 insertions(+), 27 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 72776b22d..103badf61 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -418,6 +418,50 @@ ps55_model_50t_read(uint16_t port) return 0xff; } +static uint8_t +ps55_model_50v_read(uint16_t port) +{ + switch (port) + { + case 0x100: + return ps2.planar_id & 0xff; + case 0x101: + return ps2.planar_id >> 8; + case 0x102: + return ps2.option[0]; + case 0x103: + uint8_t val = 0xff; + /* + I/O 103h - Bit 7-4: Reserved + Bit 3-0: Memory Card ID (Connector 3 or 1) + + Memory Card ID: 8h = 4 MB Memory Card IV Installed + Fh = No Card Installed + */ + switch (mem_size / 1024) + { + case 4: + if (ps2.option[1] & 0x04) val = 0xff; + else val = 0xf8; + break; + case 8: + default: + if (ps2.option[1] & 0x04) val = 0xf8; + else val = 0xf8; + break; + } + return val; + case 0x104: + return ps2.option[2]; + case 0x105: + return ps2.option[3]; + case 0x106: + return ps2.subaddr_lo; + case 0x107: + return ps2.subaddr_hi; + } + return 0xff; +} static void model_50_write(uint16_t port, uint8_t val) { @@ -716,7 +760,7 @@ model_80_write(uint16_t port, uint8_t val) } static void -ps55_model_50t_write(uint16_t port, uint8_t val)//pcem55 +ps55_model_50tv_write(uint16_t port, uint8_t val) { ps2_mca_log(" Write SysBrd %04X %02X %04X:%04X\n", port, val, cs >> 4, cpu_state.pc); switch (port) @@ -1382,6 +1426,62 @@ mem_encoding_write_cached(uint16_t addr, uint8_t val, UNUSED(void *priv)) } } +static void +mem_encoding_write_cached_ps55(uint16_t addr, uint8_t val, UNUSED(void *priv)) +{ + uint8_t old; + + switch (addr) { + case 0xe0: + ps2.mem_regs[0] = val; + break; + case 0xe1: + ps2.mem_regs[1] = val; + break; + case 0xe2: + old = ps2.mem_regs[2]; + ps2.mem_regs[2] = (ps2.mem_regs[2] & 0x80) | (val & ~0x88); + if (val & 2) { + ps2_mca_log("Clear latch - %i\n", ps2.pending_cache_miss); + if (ps2.pending_cache_miss) + ps2.mem_regs[2] |= 0x80; + else + ps2.mem_regs[2] &= ~0x80; + ps2.pending_cache_miss = 0; + } + + if ((val & 0x21) == 0x20 && (old & 0x21) != 0x20) + ps2.pending_cache_miss = 1; + if ((val & 0x21) == 0x01 && (old & 0x21) != 0x01) + ps2_cache_clean(); +#if 1 + // FIXME: Look into this!!! + if (val & 0x01) + ram_mid_mapping.flags |= MEM_MAPPING_ROM_WS; + else + ram_mid_mapping.flags &= ~MEM_MAPPING_ROM_WS; +#endif + break; + + default: + break; + } + ps2_mca_log("mem_encoding_write: addr=%02x val=%02x %04x:%04x %02x %02x\n", addr, val, CS, cpu_state.pc, ps2.mem_regs[1], ps2.mem_regs[2]); + mem_encoding_update(); + if ((ps2.mem_regs[1] & 0x10) && (ps2.mem_regs[2] & 0x21) == 0x20) { + mem_mapping_disable(&ram_low_mapping); + mem_mapping_enable(&ps2.cache_mapping); + flushmmucache(); + } else { + mem_mapping_disable(&ps2.cache_mapping); + mem_mapping_enable(&ram_low_mapping); + flushmmucache(); + } + if (ps2.option[2] & 1) /* reset memstate for E0000 - E0FFFh hole */ + { + mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } +} static void ps2_mca_board_model_70_type34_init(int is_type4, int slots) { @@ -1750,7 +1850,7 @@ ps55_mca_board_model_50t_init() device_add(&keyboard_ps2_mca_1_device); ps2.planar_read = ps55_model_50t_read; - ps2.planar_write = ps55_model_50t_write; + ps2.planar_write = ps55_model_50tv_write; device_add(&ps2_nvr_device); @@ -1790,6 +1890,51 @@ ps55_mca_board_model_50t_init() ps2.mb_vga = (vga_t *)device_add(&ps1vga_mca_device); } +void +ps55_mca_board_model_50v_init() +{ + ps2_mca_board_common_init(); + + //mem_remap_top(256); + ps2.split_addr = mem_size * 1024; + /* The slot 5 is reserved for the Integrated Fixed Disk II (an internal ESDI hard drive). */ + mca_init(5); + device_add(&keyboard_ps2_mca_1_device); + + ps2.planar_read = ps55_model_50v_read; + ps2.planar_write = ps55_model_50tv_write; + + device_add(&ps2_nvr_device); + + io_sethandler(0x00e0, 0x0002, mem_encoding_read_cached, NULL, NULL, mem_encoding_write_cached_ps55, NULL, NULL, NULL); + + ps2.mem_regs[1] = 2; + ps2.option[2] &= 0xf2; /* Bit 3-2: -Cache IDs, Bit 1: Reserved + Bit 0: Disable E0000-E0FFFh (4 KB) */ + + mem_mapping_add(&ps2.split_mapping, + (mem_size + 256) * 1024, + 256 * 1024, + ps2_read_split_ram, + ps2_read_split_ramw, + ps2_read_split_raml, + ps2_write_split_ram, + ps2_write_split_ramw, + ps2_write_split_raml, + &ram[0xa0000], + MEM_MAPPING_INTERNAL, + NULL); + mem_mapping_disable(&ps2.split_mapping); + + if (mem_size > 8192) { + /* Only 8 MB supported on planar, create a memory expansion card for the rest */ + ps2_mca_mem_fffc_init(8); + } + + if (gfxcard[0] == VID_INTERNAL) + ps2.mb_vga = (vga_t *)device_add(&ps1vga_mca_device); +} + int machine_ps55_model_50t_init(const machine_t* model) { @@ -1814,3 +1959,28 @@ machine_ps55_model_50t_init(const machine_t* model) return ret; } + +int +machine_ps55_model_50v_init(const machine_t* model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/ibmps55_m50v/56F7416.BIN", + "roms/machines/ibmps55_m50v/56F7417.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_ps2_common_init(model); + + /* + * Planar ID + * F1FFh - PS/55 model 5551-V0x, V1x + * POST (P/N 38F6933) determination: FBxx -> 5 slots (ok), F1xx -> 5 slots (ok), others -> 8 (error) + */ + ps2.planar_id = 0xf1ff; + ps55_mca_board_model_50v_init(); + + return ret; +} diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index c005c9282..bb0f0cd80 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -5508,6 +5508,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has IBM PS/55 5551-V0x, V1x firmware. */ + { + .name = "[MCA] IBM PS/55 model 5550-V0", + .internal_name = "ibmps55_m50v", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_PROPRIETARY, + .init = machine_ps55_model_50v_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX | CPU_PKG_486BL, + .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_MCA, + .flags = MACHINE_VIDEO | MACHINE_APM, + .ram = { + .min = 4096, + .max = 16384, + .step = 4096 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* 386DX/486 machines */ /* Has AMIKey F KBC firmware. */ diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 6d4f43ca6..610e272fb 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -60,6 +60,7 @@ //#define DA2_DCONFIG_FONT_HANS 2 /* for Code page 936 Simplified Chinese */ #define DA2_DCONFIG_FONT_HANT 3 /* for Code page 938 Traditional Chinese */ #define DA2_DCONFIG_MONTYPE_COLOR 0x0A +#define DA2_DCONFIG_MONTYPE_8515 0x0B #define DA2_DCONFIG_MONTYPE_MONO 0x09 #define DA2_BLT_CIDLE 0 @@ -104,9 +105,7 @@ | EFD8h | Display Adapter /J | | | X | X | X | */ /* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ -//2501 -//2500 mono -#define OldLSI 0x20 /* DA-2 or DA-3,5 */ +#define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ //#define Mon_ID3 0x10 #define FontCard 0x08 /* ? */ /* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ @@ -122,8 +121,8 @@ /* Monitor ID (imported from OS/2 DDK 1.2) */ //#define StarbuckC 0x0A //1 010b IBM 8514, 9518 color 1040x768 //#define StarbuckM 0x09 //1 001b IBM 8507, 8604 grayscale -//#define Lark_B 0x02 //0 010b IBM 9517 color 1040x768 but 4pp -//#define Dallas 0x0B //1 011b IBM 8515, 9515 color 1040x740 B palette +//#define Lark_B 0x02 //0 010b IBM 9517 color 1040x768 but 4bpp +//#define Dallas 0x0B //1 011b IBM 8515, 9515 color 1040x740 palette B /* DA2 Registers (imported from OS/2 DDK) */ #define AC_REG 0x3EE @@ -277,8 +276,6 @@ typedef struct da2_t int fctladdr; int crtcaddr; - uint8_t miscout; - uint32_t decode_mask; uint32_t vram_max; uint32_t vram_mask; @@ -319,8 +316,6 @@ typedef struct da2_t pc_timer_t timer; uint64_t da2const; - //uint8_t scrblank; - int dispon; int hdisp_on; @@ -346,7 +341,6 @@ typedef struct da2_t uint8_t *changedvram; /* (vram size - 1) >> 3 = 0x1FFFF */ uint32_t vram_display_mask; - uint32_t banked_mask; //uint32_t write_bank, read_bank; @@ -364,16 +358,9 @@ typedef struct da2_t int enable; mem_mapping_t mapping; uint8_t ram[256 * 1024]; - uint8_t font[DA2_FONTROM_SIZE]; + uint8_t *font; } mmio; - //mem_mapping_t linear_mapping; - - //uint32_t bank[2]; - //uint32_t mask; - - //int type; - struct { int bitshift_destr; int raster_op; @@ -2295,7 +2282,8 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) return da2->mmio.ram[addr]; break; case 0x10://Font ROM - //if (addr >= 0x180000) addr -= 0x40000; + if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; + if (addr >= 0x180000) addr -= 0x40000; if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); return da2->mmio.font[addr]; @@ -2975,8 +2963,8 @@ da2_reset(void* priv) da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ - da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA - 2, 1024 KB */ - da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8 ) << 2); /* Configuration 1 : Monitor ID 3 */ + da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA-II, 1024 KB */ + da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8 ) << 1); /* Configuration 1 : Monitor ID 3 */ da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ da2->fctl[0] = 0x2b; /* 3E3h:0 */ da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ @@ -3019,7 +3007,8 @@ static void *da2_init() da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ - int fonttype = device_get_config_int("font"); + int fonttype = device_get_config_int("charset"); + da2->mmio.font= malloc(DA2_FONTROM_SIZE); switch(fonttype) { case DA2_DCONFIG_FONT_HANT: @@ -3142,6 +3131,7 @@ void da2_close(void *p) free(da2->cram); free(da2->vram); free(da2->changedvram); + free(da2->mmio.font); free(da2); } @@ -3162,17 +3152,17 @@ void da2_force_redraw(void *p) static const device_config_t da2_configuration[] = { // clang-format off { - .name = "font", + .name = "charset", .description = "Charset", .type = CONFIG_SELECTION, .default_int = DA2_DCONFIG_FONT_JPAN, .selection = { { - .description = "CP932 (Japanese)", + .description = "932 (Japanese)", .value = DA2_DCONFIG_FONT_JPAN }, { - .description = "CP938 (Traditional Chinese)", + .description = "938 (Traditional Chinese)", .value = DA2_DCONFIG_FONT_HANT }, { .description = "" } @@ -3188,6 +3178,10 @@ static const device_config_t da2_configuration[] = { .description = "Color", .value = DA2_DCONFIG_MONTYPE_COLOR }, + { + .description = "IBM 8515", + .value = DA2_DCONFIG_MONTYPE_8515 + }, { .description = "Grayscale", .value = DA2_DCONFIG_MONTYPE_MONO From eeb10651da407af167026ac7f47235a5c7af7684 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 11 Feb 2025 12:08:45 +0900 Subject: [PATCH 34/82] the prev change must be restricted in CN fontset --- src/video/vid_ps55da2.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 610e272fb..011a9633f 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -55,10 +55,10 @@ #define DA2_DEBUG_BLTLOG_MAX 256*1024 #define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe #define DA2_DEBUG_BLT_USEDRESET 0xfefefe -#define DA2_DCONFIG_FONT_JPAN 0 /* for Code page 932 Japanese */ -//#define DA2_DCONFIG_FONT_HANG 1 /* for Code page 934 Hangul */ -//#define DA2_DCONFIG_FONT_HANS 2 /* for Code page 936 Simplified Chinese */ -#define DA2_DCONFIG_FONT_HANT 3 /* for Code page 938 Traditional Chinese */ +#define DA2_DCONFIG_CHARSET_JPAN 0 /* for Code page 932 Japanese */ +//#define DA2_DCONFIG_CHARSET_HANG 1 /* for Code page 934 Hangul */ +//#define DA2_DCONFIG_CHARSET_HANS 2 /* for Code page 936 Simplified Chinese */ +#define DA2_DCONFIG_CHARSET_HANT 3 /* for Code page 938 Traditional Chinese */ #define DA2_DCONFIG_MONTYPE_COLOR 0x0A #define DA2_DCONFIG_MONTYPE_8515 0x0B #define DA2_DCONFIG_MONTYPE_MONO 0x09 @@ -359,6 +359,7 @@ typedef struct da2_t mem_mapping_t mapping; uint8_t ram[256 * 1024]; uint8_t *font; + int charset; } mmio; struct { @@ -2282,8 +2283,11 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) return da2->mmio.ram[addr]; break; case 0x10://Font ROM - if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; - if (addr >= 0x180000) addr -= 0x40000; + if (da2->mmio.charset == DA2_DCONFIG_CHARSET_HANT) { + if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; + if (addr >= 0x180000) addr -= 0x40000; /* The bank 12 (180000h-19ffffh) is beyond the available ROM address range, + but the Chinese font sub card actually has this alias, and is used by DOS T5.0. */ + } if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); return da2->mmio.font[addr]; @@ -3007,14 +3011,14 @@ static void *da2_init() da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ - int fonttype = device_get_config_int("charset"); + da2->mmio.charset = device_get_config_int("charset"); da2->mmio.font= malloc(DA2_FONTROM_SIZE); - switch(fonttype) + switch(da2->mmio.charset) { - case DA2_DCONFIG_FONT_HANT: + case DA2_DCONFIG_CHARSET_HANT: da2_loadfont(DA2_FONTROM_PATH_HANT, da2); break; - case DA2_DCONFIG_FONT_JPAN: + case DA2_DCONFIG_CHARSET_JPAN: da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); break; } @@ -3155,15 +3159,15 @@ static const device_config_t da2_configuration[] = { .name = "charset", .description = "Charset", .type = CONFIG_SELECTION, - .default_int = DA2_DCONFIG_FONT_JPAN, + .default_int = DA2_DCONFIG_CHARSET_JPAN, .selection = { { .description = "932 (Japanese)", - .value = DA2_DCONFIG_FONT_JPAN + .value = DA2_DCONFIG_CHARSET_JPAN }, { .description = "938 (Traditional Chinese)", - .value = DA2_DCONFIG_FONT_HANT + .value = DA2_DCONFIG_CHARSET_HANT }, { .description = "" } } From 9ab1e35b16679c4d5870e4fb250d4b9df888e5f5 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 13 Feb 2025 20:10:23 +0900 Subject: [PATCH 35/82] added a Traditional Chinese font ROM info --- src/video/vid_ps55da2.c | 44 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 011a9633f..a19965f6f 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1533,34 +1533,32 @@ The IBM 5550 character mode addresses video memory between E0000h and E0FFFh. DOS Bunsho Program transfers 1/2 and 1/4 fonts fron the font ROM to the Extended SBCS. This bit is not used for DBCS, but some apps set it as that column is right half of DBCS. -[Font ROM Map (DA2)] -The Font ROM is accessed via 128 KB memory window located on A0000-BFFFFh. -I don't know how much data the actual Font ROM has. -Here information, I researched it by disassembling J-DOS. +[Font ROM Map (DA2, Japanese)] +The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh. -Bank 0 + Bank 0 4800- * -Bank 1, 2, 3 - * - * -Bank 4 - * -0DB6Fh ( 4800-8DB6Fh;IBMJ 100-1F7Dh) : JIS X 0208 DBCS (24 x 24) -10000-16D1Fh (90000-96D1Fh;IBMJ 2000-2183h) : IBM Extended Characters -18000-1BFCFh (98000-9BFCFh;around IBMJ 21C7-22AAh) : JIS X 0201 SBCS (13 x 30) -1C000-1FFFFh (9C000-9FFFFh;around IBMJ 22AA-238Eh) : Codepage 437 characters (13 x 30) -Bank 5 -00000-0C68Fh (A0000-AC68Fh;around IBMJ 238E-2650h) : Gaiji (24 x 24) - - * -0D09Fh (9FD20-AD09Fh;IBMJ 2384-2673h) : Gaiji 752 chs (maybe blank) -10000-13FFFh (B0000-B3FFFh;around IBMJ 271C-27FFh) : Extended SBCS (13 x 30) - -14000-147FFh (B4000-B46FFh;IBMJ 2800-2818h) : Half-width box drawing characters (7 lines * 4 parts * 64 bytes) used by DOS Bunsho -16000-17FFFh (B6000-B7FFFh;around IBMJ h) : Codepage 850 characters (13 x 30) -18000-1A3FFh (B8000-BA3FFh;around IBMJ h) : Shape Icons? (32 x 32) - - (B9580-?;IBMJ 2930-295e?) : Full-width box drawing characters + Bank 1, 2, 3 + * - * + Bank 4 + * -0DB6Fh ( 4800-8DB6Fh) : JIS X 0208 DBCS (24 x 24) (IBMJ code: 100-1F7Dh) + 10000-16D1Fh (90000-96D1Fh) : IBM Extended Characters (IBMJ code: 2ADC-2C5Fh) + 18000-1BFCFh (98000-9BFCFh) : JIS X 0201 SBCS (13 x 30) + 1C000-1FFFFh (9C000-9FFFFh) : Codepage 437 characters (13 x 30) + Bank 5 + 00000-0C68Fh (A0000-AC68Fh) : Gaiji used by DOS Bunsho + 10000-13FFFh (B0000-B3FFFh) : Extended SBCS (13 x 30) + 14000-1477Fh (B4000-B477Fh) : Half-width box drawing characters used by DOS Bunsho + 16000-17FFFh (B6000-B7FFFh) : Codepage 850 characters (13 x 30) + 18000-1A3FFh (B8000-BA3FFh) : CAD control icons and box drawing characters (32 x 32) Some models have the signature 80h, 01h placed at Bank 0:1AFFEh. (it disables hardware text drawing in OS/2 J1.3) +[Font ROM Map (DA3, Traditional Chinese)] + Bank 0 - 11 : Valid Font ROM data + Bank 12 : Alias of bank 11 (At least, DOS T5.0 uses this on purpose.) + Bank 13 : All addresses return 0xFF + [Gaiji RAM Map (DA2)] Bank 0 00000-1FFFFh placed between A0000h-BFFFFh 00000-1F7FFh(A0000-BF7FFh): Gaiji Non-resident (Kuten 103-114 ku,IBM: 2674-2ADBh) 1008 chs 128 bytes From 466bcc68b40328e13d236f4973f0592c7894115a Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 08:09:43 +0900 Subject: [PATCH 36/82] update header files I forgot updating header files --- src/include/86box/fdc.h | 4 ++-- src/include/86box/machine.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index 0d71dd374..0c2e5ce06 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -52,7 +52,7 @@ #define FDC_FLAG_ALI 0x800 /* ALi M512x / M1543C */ #define FDC_FLAG_NO_DSR_RESET 0x1000 /* Has no DSR reset */ #define FDC_FLAG_NEC 0x2000 /* Is NEC upd765-compatible */ -#define FDC_FLAG_PS55 0x4000 /* PS/55 */ +#define FDC_FLAG_PS2 0x4000 /* PS/2, PS/55 */ #define FDC_FLAG_SEC 0x10000 /* Is Secondary */ #define FDC_FLAG_TER 0x20000 /* Is Tertiary */ #define FDC_FLAG_QUA 0x40000 /* Is Quaternary */ @@ -253,7 +253,7 @@ extern const device_t fdc_at_qua_device; extern const device_t fdc_at_actlow_device; extern const device_t fdc_at_ps1_device; extern const device_t fdc_at_ps1_2121_device; -extern const device_t fdc_at_ps55_device; +extern const device_t fdc_at_ps2_device; extern const device_t fdc_at_smc_device; extern const device_t fdc_at_ali_device; extern const device_t fdc_at_winbond_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index fe867a4dc..3efb5a8e8 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -887,7 +887,8 @@ extern int machine_ps2_model_70_type3_init(const machine_t *); extern int machine_ps2_model_80_init(const machine_t *); extern int machine_ps2_model_80_axx_init(const machine_t *); extern int machine_ps2_model_70_type4_init(const machine_t *); -extern int machine_ps55_model_50t_init(const machine_t*); +extern int machine_ps55_model_50t_init(const machine_t*);; +extern int machine_ps55_model_50v_init(const machine_t*); /* m_tandy.c */ extern int tandy1k_eeprom_read(void); From cb67a389b17ec1aa03be9a0fa51e631b2160e659 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 08:14:31 +0900 Subject: [PATCH 37/82] modified ps/55 configuration, added a mca func I forgot updating some files --- src/86box.c | 2 +- src/config.c | 6 ++++++ src/mca.c | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/86box.c b/src/86box.c index 82eedbd78..9b77263a2 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1062,7 +1062,7 @@ pc_init_modules(void) void pc_send_ca(uint16_t sc) { - /* Use R-Alt because 5576-002 keyboard assigns L-Alt as */ + /* Use R-Alt because PS/55 DOS assigns L-Alt as Kanji */ keyboard_input(1, 0x1D); /* Ctrl key pressed */ keyboard_input(1, 0x138); /* R-Alt key pressed */ keyboard_input(1, sc); diff --git a/src/config.c b/src/config.c index 2c0781028..7a5d76465 100644 --- a/src/config.c +++ b/src/config.c @@ -456,6 +456,7 @@ load_video(void) ibm8514_active = ibm8514_standalone_enabled; xga_standalone_enabled = !!ini_section_get_int(cat, "xga", 0); xga_active = xga_standalone_enabled; + da2_standalone_enabled = !!ini_section_get_int(cat, "da2", 0); show_second_monitors = !!ini_section_get_int(cat, "show_second_monitors", 1); video_fullscreen_scale_maximized = !!ini_section_get_int(cat, "video_fullscreen_scale_maximized", 0); @@ -2013,6 +2014,11 @@ save_video(void) else ini_section_set_int(cat, "xga", xga_standalone_enabled); + if (da2_standalone_enabled == 0) + ini_section_delete_var(cat, "da2"); + else + ini_section_set_int(cat, "da2", da2_standalone_enabled); + // TODO for (uint8_t i = 1; i < GFXCARD_MAX; i ++) { if (gfxcard[i] == 0) diff --git a/src/mca.c b/src/mca.c index 871060bb4..a14fea6fa 100644 --- a/src/mca.c +++ b/src/mca.c @@ -101,3 +101,19 @@ mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t v } } } + +void +mca_add_to_slot(uint8_t (*read)(int addr, void* priv), void (*write)(int addr, uint8_t val, void* priv), uint8_t(*feedb)(void* priv), void (*reset)(void* priv), void* priv, int c) +{ + if (mca_card_read[c] || mca_card_write[c]) + { + //pclog("cannot add the device to slot %d\n", num); + return; + } + mca_card_read[c] = read; + mca_card_write[c] = write; + mca_card_feedb[c] = feedb; + mca_card_reset[c] = reset; + mca_priv[c] = priv; + return; +} From bfac770b4e19cb1bc23396a98263e6f1fd097208 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 08:27:17 +0900 Subject: [PATCH 38/82] reupload without code modification --- src/include/86box/vid_ps55da2.h | 48 +- src/video/vid_ps55da2.c | 6444 +++++++++++++++---------------- 2 files changed, 3246 insertions(+), 3246 deletions(-) diff --git a/src/include/86box/vid_ps55da2.h b/src/include/86box/vid_ps55da2.h index 70007be19..f029b5751 100644 --- a/src/include/86box/vid_ps55da2.h +++ b/src/include/86box/vid_ps55da2.h @@ -1,24 +1,24 @@ -/* - * 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. - * - * IBM PS/55 Display Adapter II emulation. - * - * - * - * Authors: Akamaki. - * - * Copyright 2024 Akamaki. - */ - -#ifndef VIDEO_DA2_DEVICE_H -#define VIDEO_DA2_DEVICE_H - -#ifdef EMU_DEVICE_H -extern const device_t ps55da2_device; -#endif -#endif /*VIDEO_DA2_DEVICE_H*/ +/* + * 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. + * + * IBM PS/55 Display Adapter II emulation. + * + * + * + * Authors: Akamaki. + * + * Copyright 2024 Akamaki. + */ + +#ifndef VIDEO_DA2_DEVICE_H +#define VIDEO_DA2_DEVICE_H + +#ifdef EMU_DEVICE_H +extern const device_t ps55da2_device; +#endif +#endif /*VIDEO_DA2_DEVICE_H*/ diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index a19965f6f..0ac136630 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1,3222 +1,3222 @@ -/* - * 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. - * - * IBM PS/55 Display Adapter II emulation. - * - * Authors: Akamaki. - * - * Copyright 2024 Akamaki. - */ - -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/device.h> -#include <86box/io.h> -#include <86box/machine.h> -#include <86box/mem.h> -#include <86box/timer.h> -#include <86box/mca.h> -#include <86box/rom.h> -#include <86box/plat.h> -#include <86box/thread.h> -#include <86box/video.h> -#include <86box/vid_ps55da2.h> -#include <86box/vid_svga.h> -#include <86box/vid_svga_render.h> -#include "cpu.h" - -#define DA2_FONTROM_PATH_JPAN "roms/video/da2/94X1320.BIN" -#define DA2_FONTROM_PATH_HANT "roms/video/da2/23F2698.BIN" -#define DA2_FONTROM_SIZE 1536*1024 -#define DA2_FONTROM_BASESBCS 0x98000 -#define DA2_GAIJIRAM_SBCS 0x34000 -#define DA2_GAIJIRAM_SBEX 0x3c000 -#define DA2_INVALIDACCESS8 0xff -#define DA2_MASK_MMIO 0x1ffff -#define DA2_MASK_GRAM 0x1ffff -#define DA2_MASK_CRAM 0xfff -#define DA2_MASK_GAIJIRAM 0x3ffff -#define DA2_PIXELCLOCK 58000000.0 -#define DA2_BLT_MEMSIZE 0x100 -#define DA2_BLT_REGSIZE 0x40 -#define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) -#define DA2_DEBUG_BLTLOG_MAX 256*1024 -#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe -#define DA2_DEBUG_BLT_USEDRESET 0xfefefe -#define DA2_DCONFIG_CHARSET_JPAN 0 /* for Code page 932 Japanese */ -//#define DA2_DCONFIG_CHARSET_HANG 1 /* for Code page 934 Hangul */ -//#define DA2_DCONFIG_CHARSET_HANS 2 /* for Code page 936 Simplified Chinese */ -#define DA2_DCONFIG_CHARSET_HANT 3 /* for Code page 938 Traditional Chinese */ -#define DA2_DCONFIG_MONTYPE_COLOR 0x0A -#define DA2_DCONFIG_MONTYPE_8515 0x0B -#define DA2_DCONFIG_MONTYPE_MONO 0x09 - -#define DA2_BLT_CIDLE 0 -#define DA2_BLT_CFILLRECT 1 -#define DA2_BLT_CFILLTILE 2 -#define DA2_BLT_CCOPYF 3 -#define DA2_BLT_CCOPYR 4 -#define DA2_BLT_CPUTCHAR 5 -#define DA2_BLT_CDONE 6 -#define DA2_BLT_CLOAD 7 -/* POS ID = 0xeffe : Display Adapter II, III, V */ -#define DA2_POSID_H 0xef -#define DA2_POSID_L 0xfe -/* - [Identification] - POS ID SYS ID - EFFFh * Display Adapter (PS/55 Model 5571-S0A) [Toledo] - E013h * Layout Display Terminal (PS/55-5571 RPQ model) [LDT] - EFFEh * Display Adapter II (I/O 3E0:0A = xx0x xxxx) [Atlas] - |- FFF2h Display Adapter B2 (I/O 3E0:0A = xx1x xxxx) (PS/55 Model 5530Z-SX) - |- FDFEh Display Adapter B2 (I/O 3E0:0A = xx1x xxxx) (PS/55 Model 5550-V2) - |- * Display Adapter III,V (I/O 3E0:0A = xx1x xxxx) - ECECh FF4Fh Display Adapter B1 (PS/55 Model 5531Z-SX) [Atlas-KENT] - |- * Display Adapter IV - ECCEh * Display Adapter IV - 901Fh * Display Adapter A2 - 901Dh * Display Adapter A1 [Atlas II] - 901Eh * Plasma Display Adapter - EFD8h * Display Adapter/J [Atlas-SP2] - - [Japanese DOS and Display Adapter compatibility] - | POS ID | Adapter Name | K3.31 | J4.04 | J5.02 | OS2 J1.3 | Win3 | - |------------|-----------------------------|:-----:|:-----:|:-----:|:--------:|:----:| - | EFFFh | Display Adapter | X | | | ? | | - | FFEDh | ? [Atlas EVT] | X | | | ? | | - | FFFDh | ? [LDT EVT] | X | | | ? | | - | EFFEh | Display Adapter II,III,V,B2 | X | X | X | X | X | - | E013h | ? [LDT] | X | X | X | X | | - | ECCEh | Display Adapter IV | | X | X | X | | - | ECECh | Display Adapter IV,B1 | | X | X | X | X | - | 9000-901Fh | Display Adapter A1,A2 | | X | X | | X | - | EFD8h | Display Adapter /J | | | X | X | X | -*/ -/* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ -#define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ -//#define Mon_ID3 0x10 -#define FontCard 0x08 /* ? */ -/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ -#define Page_One 0x06 /* 80000h 110b */ -#define Page_Two 0x05 /* 100000h 101b */ -#define Page_Four 0x03 /* 200000h 011b */ - -/* IO 3E0/3E1:0Bh Hardware Configuration Value H (imported from OS/2 DDK) */ -#define AddPage 0x08 /* ? */ -//#define Mon_ID2 0x04 -//#define Mon_ID1 0x02 -//#define Mon_ID0 0x01 -/* Monitor ID (imported from OS/2 DDK 1.2) */ -//#define StarbuckC 0x0A //1 010b IBM 8514, 9518 color 1040x768 -//#define StarbuckM 0x09 //1 001b IBM 8507, 8604 grayscale -//#define Lark_B 0x02 //0 010b IBM 9517 color 1040x768 but 4bpp -//#define Dallas 0x0B //1 011b IBM 8515, 9515 color 1040x740 palette B - -/* DA2 Registers (imported from OS/2 DDK) */ -#define AC_REG 0x3EE -#define AC_DMAE 0x80 -#define AC_FONT_SEL 0x40 -#define FONT_BANK 0x3EF -#define LS_INDEX 0x3E0 -#define LS_DATA 0x3E1 -#define LS_RESET 0x00 -#define LS_MODE 0x02 -#define LS_STATUS 0x03 /* added */ -#define LS_MMIO 0x08 /* added */ -#define LS_CONFIG1 0x0a -#define LS_CONFIG2 0x0b /* added */ -#define LF_INDEX 0x3e2 -#define LF_DATA 0x3e3 -#define LF_MMIO_SEL 0x08 /* added */ -#define LF_MMIO_ADDR 0x0A /* added */ -#define LF_MMIO_MODE 0x0B /* added */ -#define LC_INDEX 0x3E4 -#define LC_DATA 0x3E5 -#define LC_HORIZONTAL_TOTAL 0x00 -#define LC_H_DISPLAY_ENABLE_END 0x01 -#define LC_START_H_BLANKING 0x02 -#define LC_END_H_BLANKING 0x03 -#define LC_START_HSYNC_PULSE 0x04 -#define LC_END_HSYNC_PULSE 0x05 -#define LC_VERTICAL_TOTALJ 0x06 -#define LC_CRTC_OVERFLOW 0x07 -#define LC_PRESET_ROW_SCANJ 0x08 -#define LC_MAXIMUM_SCAN_LINE 0x09 -#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_ROW_CURSOR_LOC 0x0E -#define LC_CURSOR_LOC_LOWJ 0x0F -#define LC_COLUMN_CURSOR_LOC 0x0F -#define LC_VERTICAL_SYNC_START 0x10 -#define LC_LIGHT_PEN_HIGH 0x10 -#define LC_VERTICAL_SYNC_END 0x11 -#define LC_LIGHT_PEN_LOW 0x11 -#define LC_V_DISPLAY_ENABLE_END 0x12 -#define LC_OFFSET 0x13 -#define LC_UNDERLINE_LOCATION 0x14 -#define LC_START_VERTICAL_BLANK 0x15 -#define LC_END_VERTICAL_BLANK 0x16 -#define LC_LC_MODE_CONTROL 0x17 -#define LC_LINE_COMPAREJ 0x18 -#define LC_START_H_DISPLAY_ENAB 0x19 -#define LC_START_V_DISPLAY_ENAB 0x1A -#define LC_VIEWPORT_COMMAND 0x1B -#define LC_VIEWPORT_SELECT 0x1C -#define LC_VIEWPORT_PRIORITY 0x1D -#define LC_COMMAND 0x1E -#define LC_COMPATIBILITY 0x1F -#define LC_VIEWPORT_NUMBER 0x1F -#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 LG_INDEX 0x3EA -#define LG_DATA 0x3EB -#define LG_SET_RESETJ 0x00 -#define LG_ENABLE_SRJ 0x01 -#define LG_COLOR_COMPAREJ 0x02 -#define LG_DATA_ROTATION 0x03 -#define LG_READ_MAP_SELECT 0x04 -#define LG_MODE 0x05 -#define LG_COMPLEMENT 0x06 -#define LG_COLOR_DONT_CARE 0x07 -#define LG_BIT_MASK_LOW 0x08 -#define LG_BIT_MASK_HIGH 0x09 -#define LG_MAP_MASKJ 0x0A -#define LG_COMMAND 0x0B -#define LG_SET_RESET_2 0x10 - -#ifndef RELEASE_BUILD -#define ENABLE_DA2_LOG 1 -#endif - -#ifdef ENABLE_DA2_LOG -int da2_do_log = ENABLE_DA2_LOG; - -static void -da2_log(const char* fmt, ...) -{ - va_list ap; - - if (da2_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -# define da2_log(fmt, ...) -#endif -#ifndef RELEASE_BUILD -# define ENABLE_DA2_DEBUGBLT 1 -#endif - -typedef struct da2_t -{ - //mem_mapping_t vmapping; - mem_mapping_t cmapping; - - //uint8_t crtcreg; - uint8_t ioctl[16]; - uint8_t fctl[32]; - uint16_t crtc[128]; - uint8_t gdcreg[64]; - uint8_t reg3ee[16]; - int gdcaddr; - uint8_t attrc[0x40]; - int attraddr, attrff; - int attr_palette_enable; - //uint8_t seqregs[64]; - int outflipflop; - int inflipflop; - int iolatch; - - int ioctladdr; - int fctladdr; - int crtcaddr; - - uint32_t decode_mask; - uint32_t vram_max; - uint32_t vram_mask; - - uint32_t gdcla[8]; - uint32_t gdcinput[8]; - uint32_t gdcsrc[8]; - uint32_t debug_vramold[8]; - - uint8_t dac_mask, dac_status; - int dac_read, dac_write, dac_pos; - int dac_r, dac_g; - - uint8_t cgastat; - - uint8_t plane_mask; - - int fb_only; - - int fast; - uint8_t colourcompare, colournocare; - int readmode, writemode, readplane; - uint8_t writemask; - uint32_t charseta, charsetb; - - uint8_t egapal[16]; - uint32_t pallook[512]; - PALETTE vgapal; - - int vtotal, dispend, vsyncstart, split, vblankstart; - int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; - int lowres, interlace; - int rowcount; - double clock; - uint32_t ma_latch, ca_adj; - - uint64_t dispontime, dispofftime; - pc_timer_t timer; - uint64_t da2const; - - int dispon; - int hdisp_on; - - uint32_t ma, maback, ca; - int vc; - int sc; - int linepos, vslines, linecountff, oddeven; - int con, cursoron, blink, blinkconf; - int scrollcache; - int char_width; - - int firstline, lastline; - int firstline_draw, lastline_draw; - int displine; - - /* Attribute Buffer E0000-E0FFFh (4 KB) */ - uint8_t *cram; - /* (cram size - 1) >> 3 = 0xFFF */ - //uint32_t cram_display_mask; - /* APA Buffer A0000-BFFFFh (128 KB) */ - uint8_t *vram; - /* addr >> 12 = xx000h */ - uint8_t *changedvram; - /* (vram size - 1) >> 3 = 0x1FFFF */ - uint32_t vram_display_mask; - - //uint32_t write_bank, read_bank; - - int fullchange; - - void (*render)(struct da2_t* da2); - - /*If set then another device is driving the monitor output and the SVGA - card should not attempt to display anything */ - int override; - - /* end VGA compatible regs*/ - struct - { - int enable; - mem_mapping_t mapping; - uint8_t ram[256 * 1024]; - uint8_t *font; - int charset; - } mmio; - - struct { - int bitshift_destr; - int raster_op; - uint8_t payload[DA2_BLT_MEMSIZE]; - int32_t reg[DA2_BLT_REGSIZE];//must be signed int - int32_t* debug_reg;//for debug - int debug_reg_ip;//for debug - int payload_addr; - pc_timer_t timer; - int64_t timerspeed; - int exec; - int indata; - int32_t destaddr; - int32_t srcaddr; - int32_t size_x, tile_w; - int32_t size_y; - int16_t destpitch; - int16_t srcpitch; - int32_t fcolor; - int32_t maskl, maskr; - int x, y; - } bitblt; - - FILE* mmdbg_fp; - FILE* mmrdbg_fp; - uint32_t mmdbg_vidaddr; - uint32_t mmrdbg_vidaddr; - - uint8_t pos_regs[8]; - svga_t *mb_vga; - uint8_t monitorid; - - int old_pos2; -} da2_t; - -void da2_recalctimings(da2_t* da2); -static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p); -void da2_bitblt_exec(void* p); -void da2_updatevidselector(da2_t* da2); -void da2_reset_ioctl(da2_t* da2); -static void da2_reset(void* priv); - -typedef union { - uint32_t d; - uint8_t b[4]; -} DA2_VidSeq32; - -typedef struct { - uint32_t p8[8]; -} pixel32; - -/* safety read for internal functions */ -uint32_t DA2_readvram_s(uint32_t addr, da2_t* da2) -{ - if (addr & ~da2->vram_mask) return -1; - return da2->vram[addr]; -} - -void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32* srcpx, da2_t* da2) -{ - uint32_t writepx[8]; - destaddr &= 0xfffffffe;/* align to word address to work bit shift correctly */ - //da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); - da2->changedvram[(da2->vram_display_mask & destaddr) >> 12] = changeframecount; - da2->changedvram[(da2->vram_display_mask & (destaddr+1)) >> 12] = changeframecount; - destaddr <<= 3; - /* read destination data with big endian order */ - for (int i = 0; i < 8; i++) - writepx[i] = DA2_readvram_s((destaddr + 24) | i, da2) - | (DA2_readvram_s((destaddr + 16) | i, da2) << 8) - | (DA2_readvram_s((destaddr + 8) | i, da2) << 16) - | (DA2_readvram_s((destaddr + 0) | i, da2) << 24); - - DA2_VidSeq32 mask32in; mask32in.d = (uint32_t)mask; - DA2_VidSeq32 mask32; mask32.d = 0; - mask32.b[3] = mask32in.b[0]; - mask32.b[2] = mask32in.b[1]; - mask32.d &= 0xffff0000; - for (int i = 0; i < 8; i++) - { - if (da2->bitblt.bitshift_destr > 0) - srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; - switch (da2->bitblt.raster_op) { - case 0x00: /* None */ - writepx[i] &= ~mask32.d; - writepx[i] |= srcpx->p8[i] & mask32.d; - break; - case 0x01: /* AND */ - writepx[i] &= srcpx->p8[i] | ~mask32.d; - break; - case 0x02: /* OR */ - writepx[i] |= srcpx->p8[i] & mask32.d; - break; - case 0x03: /* XOR */ - writepx[i] ^= srcpx->p8[i] & mask32.d; - break; - } - } - for (int i = 0; i < 8; i++) { - da2->vram[(da2->vram_mask & destaddr) | i] = (writepx[i] >> 24) & 0xff; - da2->vram[(da2->vram_mask & (destaddr + 8)) | i] = (writepx[i] >> 16) & 0xff; - } -} - -void DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t* da2) -{ - pixel32 srcpx; - //fill data with input color - for (int i = 0; i < 8; i++) - srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0;//read in word - - DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); -} -/* -Param Desc -01 Color -03 Bit Shift -04 Select plane? -05 Dir(10 or 11) + Command?(40 or 48) -08 Mask Left -09 Mask Right -0A Plane Mask? -0B ROP?(8h or 200h + 0-3h) -0D -20 Exec (1) -21 ? -22 ? -23 Tile W -28 Tile H -29 Dest Addr -2A Src Addr -2B Tile Addr -33 Size W -35 Size H - -*/ -void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) -{ - pixel32 srcpx; - srcaddr &= 0xfffffffe; - srcaddr <<= 3; - for (int i = 0; i < 8; i++) - srcpx.p8[i] = DA2_readvram_s((srcaddr + 24) | i, da2) - | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) - | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) - | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24);//read in word - - DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); -} -void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) -{ - pixel32 srcpx; - if (srcaddr >= DA2_FONTROM_SIZE) { - da2_log("DA2 Putchar Addr Error %x\n", srcaddr); - return; - } - for (int i = 0; i < 8; i++) - srcpx.p8[i] = ((uint32_t)da2->mmio.font[srcaddr] << 24) - | ((uint32_t)da2->mmio.font[srcaddr + 1] << 16) - | ((uint32_t)da2->mmio.font[srcaddr + 2] << 8) - | ((uint32_t)da2->mmio.font[srcaddr + 3] << 0);//read in word - - DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); -} -#ifdef ENABLE_DA2_DEBUGBLT -uint8_t pixel1tohex(uint32_t addr, int index, da2_t* da2) { - uint8_t pixeldata = 0; - for (int j = 0; j < 8; j++) { - if (da2->vram[(da2->vram_mask & (addr << 3)) | j] & (1 << (7 - index))) pixeldata++; - } - return pixeldata; -} -void print_pixelbyte(uint32_t addr, da2_t* da2) { - for (int i = 0; i < 8; i++) - { - pclog("%X", pixel1tohex(addr, i, da2)); - } -} -void print_bytetobin(uint8_t b) { - for (int i = 0; i < 8; i++) - { - if(b & 0x80) - pclog("1"); - else - pclog("0"); - b <<= 1; - } -} -//Convert internal char code to Shift JIS code -inline int isKanji1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); } -inline int isKanji2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); } -uint16_t IBMJtoSJIS(uint16_t knj) -{ - if (knj < 0x100) return 0xffff; - knj -= 0x100; - if (knj <= 0x1f7d) - ;/* do nothing */ - else if (knj >= 0xb700 && knj <= 0xb75f) { - knj -= 0x90ec; - } - else if (knj >= 0xb3f0 && knj <= 0xb67f) { - knj -= 0x906c; - } - else if (knj >= 0x8000 && knj <= 0x8183) - { - knj -= 0x5524; - } - else - return 0xffff; - uint32_t knj1 = knj / 0xBC; - uint32_t knj2 = knj - (knj1 * 0xBC); - knj1 += 0x81; - if (knj1 > 0x9F) knj1 += 0x40; - knj2 += 0x40; - if (knj2 > 0x7E) knj2++; - //if (!isKanji1(knj1)) return 0xffff; - //if (!isKanji2(knj2)) return 0xffff; - knj = knj1 << 8; - knj |= knj2; - return knj; -} -#endif -void da2_bitblt_load(da2_t* da2) -{ - uint32_t value32; - uint64_t value64; - da2_log("BITBLT loading params\n"); - //da2_log("BitBlt memory:\n"); - //if (da2->bitblt.payload[0] != 0) - // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) - // { - // int i = j * 8; - // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - // da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); - // } - int i = 0; - while (i < DA2_BLT_MEMSIZE) - { - if (da2->bitblt.reg[0x20] & 0x1) - break; - switch (da2->bitblt.payload[i]) { - case 0x88: - case 0x89: - case 0x95: - value32 = da2->bitblt.payload[i + 3]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; - i += 3; - break; - case 0x91: - value32 = da2->bitblt.payload[i + 5]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 4]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 3]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; - i += 5; - break; - case 0x99: - value64 = da2->bitblt.payload[i + 7]; - value64 <<= 8; - value64 = da2->bitblt.payload[i + 6]; - value64 <<= 8; - value64 = da2->bitblt.payload[i + 5]; - value64 <<= 8; - value64 |= da2->bitblt.payload[i + 4]; - value64 <<= 8; - value64 |= da2->bitblt.payload[i + 3]; - value64 <<= 8; - value64 |= da2->bitblt.payload[i + 2]; - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; - da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); - i += 7; - break; - case 0x00: - break; - default: - da2_log("da2_ParseBLT: Unknown PreOP!\n"); - break; - } - i++; - } - da2->bitblt.exec = DA2_BLT_CIDLE; - /* clear payload memory */ - memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - da2->bitblt.payload_addr = 0; - /* [89] 20: 0001 (1) then execute payload */ - if (da2->bitblt.reg[0x20] & 0x1) - { -#ifdef ENABLE_DA2_DEBUGBLT - for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { - //if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); - } - for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { - da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; - } - da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * (da2->bitblt.debug_reg_ip + 1) - 1] = 0; - da2->bitblt.debug_reg_ip++; - if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; -#endif - da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f);//set bit shift - da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03;//01 AND, 03 XOR - da2_log("bitblt execute 05: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); - for (int i = 0; i <= 0xb; i++) - da2_log("%02x ", da2->gdcreg[i]); - da2_log("\n"); - - da2->bitblt.destaddr = da2->bitblt.reg[0x29]; - da2->bitblt.size_x = da2->bitblt.reg[0x33]; - da2->bitblt.size_y = da2->bitblt.reg[0x35]; - da2->bitblt.destpitch = da2->bitblt.reg[0x21]; - da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; - if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; - { - da2->bitblt.destaddr -= 2; - da2->bitblt.size_x += 1; - da2->bitblt.destpitch -= 2; - da2->bitblt.srcpitch -= 2; - } - da2->bitblt.fcolor = da2->bitblt.reg[0x0]; - da2->bitblt.maskl = da2->bitblt.reg[0x8]; - da2->bitblt.maskr = da2->bitblt.reg[0x9]; - da2->bitblt.x = 0; - da2->bitblt.y = 0; - da2->bitblt.exec = DA2_BLT_CDONE; - timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - - if (da2->bitblt.reg[0x2f] < 0x80)//MS Paint 3.1 will cause hang up in 256 color mode - { - da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); - da2->bitblt.exec = DA2_BLT_CDONE; - } - else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ - da2->bitblt.exec = DA2_BLT_CPUTCHAR; - /* Todo: addressing */ - //if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; - //{ - // da2->bitblt.destaddr += 2; - // da2->bitblt.size_x -= 1; - // da2->bitblt.destpitch += 2; - // da2->bitblt.srcpitch += 2; - //} - uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; - uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; - da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2; - da2->bitblt.destaddr += 2; - da2->bitblt.srcpitch = 0; - da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ - da2->bitblt.bitshift_destr += 1; - da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); - } - else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { - da2->bitblt.exec = DA2_BLT_CPUTCHAR; - uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; - uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; - da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; - da2->bitblt.destaddr += 2; - da2->bitblt.srcpitch = 0; - da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ - da2->bitblt.bitshift_destr += 1; - da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); - } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {/* Fill a rectangle(or draw a line) */ - da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); - da2->bitblt.exec = DA2_BLT_CFILLRECT; - da2->bitblt.destaddr += 2; - } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */ - da2->bitblt.exec = DA2_BLT_CFILLTILE; - da2->bitblt.destaddr += 2; - da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; - da2->bitblt.tile_w = da2->bitblt.reg[0x28]; - da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); - } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle (transfer tile data multiple times) */ - da2->bitblt.exec = DA2_BLT_CFILLTILE; - da2->bitblt.destaddr += 2; - da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; - da2->bitblt.tile_w = da2->bitblt.reg[0x28]; - da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); - } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) {/* Block transfer (range copy) */ - da2->bitblt.exec = DA2_BLT_CCOPYF; - da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; - da2->bitblt.destaddr += 2; - da2_log("copy block src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); - } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) {/* Block copy but reversed direction */ - da2->bitblt.exec = DA2_BLT_CCOPYR; - da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; - da2->bitblt.destaddr -= 2; - da2->bitblt.srcaddr -= 2; - da2_log("copy blockR src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); - //da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); - } - } -} -void da2_bitblt_exec(void* p) -{ - da2_t* da2 = (da2_t*)p; - timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - //da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); - switch (da2->bitblt.exec) - { - case DA2_BLT_CIDLE: - timer_disable(&da2->bitblt.timer); - break; - case DA2_BLT_CLOAD: - da2->bitblt.indata = 0; - da2_bitblt_load(da2); - break; - case DA2_BLT_CFILLRECT: - //da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; - } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - } - else if (da2->bitblt.x == 0) { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr += 2; - break; - case DA2_BLT_CFILLTILE: - int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; - } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - } - else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr += 2; - break; - case DA2_BLT_CCOPYF: - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; - } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - da2->bitblt.srcaddr += da2->bitblt.srcpitch + 2; - } - else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr += 2; - da2->bitblt.srcaddr += 2; - break; - case DA2_BLT_CCOPYR: - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; - } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr -= da2->bitblt.destpitch; - da2->bitblt.srcaddr -= da2->bitblt.srcpitch; - da2->bitblt.destaddr -= 2; - da2->bitblt.srcaddr -= 2; - } - else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr -= 2; - da2->bitblt.srcaddr -= 2; - break; - case DA2_BLT_CPUTCHAR: - //da2->bitblt.y += 2; - da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; - pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); - //da2->bitblt.srcaddr += 2; - if(da2->bitblt.reg[0x12] < 0x100) - da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; - else - da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; - print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); - print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); - pclog("\n"); - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - //if (1) { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 3) - { - da2->bitblt.exec = DA2_BLT_CDONE; - } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += 130; - //da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - //da2->bitblt.srcaddr += -1; - } - else if (da2->bitblt.x == 0) { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - //da2->bitblt.x++; - } - else { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - //da2->bitblt.x++; - } - //da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2; - ////da2->bitblt.srcaddr += 2; - //da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; - break; - case DA2_BLT_CDONE: - /* initialize regs for debug dump */ - for (int i = 0; i < DA2_BLT_REGSIZE; i++) { - if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; - } - if(da2->bitblt.indata) da2->bitblt.exec = DA2_BLT_CLOAD; - else da2->bitblt.exec = DA2_BLT_CIDLE; - break; - } -} -void da2_bitblt_dopayload(da2_t* da2) { - if (da2->bitblt.exec == DA2_BLT_CIDLE) - { - da2->bitblt.exec = DA2_BLT_CLOAD; - //timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ - da2_log("da2 Do bitblt\n"); - while (da2->bitblt.exec != DA2_BLT_CIDLE) - { - da2_bitblt_exec(da2); - } - da2_log("da2 End bitblt %x\n", da2->bitblt.exec); - } -} - -void da2_out(uint16_t addr, uint16_t val, void *p) -{ - da2_t *da2 = (da2_t *)p; - int oldval; -/* -3E0 3E1 Sequencer Registers (undoc) -3E2 3E3 Font Registers (undoc) -3E4 3E5 CRT Control Registers (undoc) -3E8 3E9 Attribute Controller Registers (undoc) -3EA 3EB 3EC Graphics Contoller Registers -*/ - switch (addr) - { - case 0x3c6: /* PEL Mask */ - da2->dac_mask = val; - break; - case 0x3C7: /* Read Address */ - da2->dac_read = val; - da2->dac_pos = 0; - break; - case 0x3C8: /* Write Address */ - da2->dac_write = val; - da2->dac_read = val - 1; - da2->dac_pos = 0; - break; - case 0x3C9: /* Data */ - //da2_log("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI); - da2->dac_status = 0; - da2->fullchange = changeframecount; - switch (da2->dac_pos) - { - case 0: - da2->dac_r = val; - da2->dac_pos++; - break; - case 1: - da2->dac_g = val; - da2->dac_pos++; - break; - case 2: - da2->vgapal[da2->dac_write].r = da2->dac_r; - da2->vgapal[da2->dac_write].g = da2->dac_g; - da2->vgapal[da2->dac_write].b = val; - //if (da2->ramdac_type == RAMDAC_8BIT) - // da2->pallook[da2->dac_write] = makecol32(da2->vgapal[da2->dac_write].r, da2->vgapal[da2->dac_write].g, da2->vgapal[da2->dac_write].b); - //else - da2->pallook[da2->dac_write] = makecol32((da2->vgapal[da2->dac_write].r & 0x3f) * 4, (da2->vgapal[da2->dac_write].g & 0x3f) * 4, (da2->vgapal[da2->dac_write].b & 0x3f) * 4); - da2->dac_pos = 0; - da2->dac_write = (da2->dac_write + 1) & 255; - break; - } - break; - case LS_INDEX: - da2->ioctladdr = val; - break; - case LS_DATA: - //da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->ioctladdr, val, cs >> 4, cpu_state.pc); - if (da2->ioctladdr > 0xf) return; - if (da2->ioctl[da2->ioctladdr & 15] != val) - da2_log("ioctl changed %x: %x -> %x %04X:%04X\n", da2->ioctladdr & 15, da2->ioctl[da2->ioctladdr & 15], val, cs >> 4, cpu_state.pc); - oldval = da2->ioctl[da2->ioctladdr]; - da2->ioctl[da2->ioctladdr] = val; - if (oldval != val) { - if (da2->ioctladdr == LS_RESET && val & 0x01) /* Reset register */ - da2_reset_ioctl(da2); - else if (da2->ioctladdr == LS_MODE && ((oldval ^ val) & 0x03)) /* Mode register */ - { - da2->fullchange = changeframecount; - da2_recalctimings(da2); - da2_updatevidselector(da2); - } - else if (da2->ioctladdr == LS_MMIO && (!(val & 0x01))) /* MMIO register */ - { - //da2->bitblt.indata = 1; - } - } - break; - case LF_INDEX: - da2->fctladdr = val; - break; - case LF_DATA: - //da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); - if (da2->fctladdr > 0x1f) return; - if (da2->fctl[da2->fctladdr & 0x1f] != val) - da2_log("fctl changed %x: %x -> %x %04X:%04X\n", da2->fctladdr & 0x1f, da2->fctl[da2->fctladdr & 0x1f], val, cs >> 4, cpu_state.pc); - oldval = da2->fctl[da2->fctladdr]; - da2->fctl[da2->fctladdr] = val; - if (da2->fctladdr == 0 && oldval != val) - { - da2->fullchange = changeframecount; - da2_recalctimings(da2); - } - break; - case LC_INDEX: - da2->crtcaddr = val; - break; - case LC_DATA: - if (da2->crtcaddr > 0x1f) return; - //if (!(da2->crtcaddr == LC_CURSOR_LOC_HIGH || da2->crtcaddr == LC_CURSOR_LOC_LOWJ)) - // da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc); - if (!(da2->crtc[da2->crtcaddr] ^ val)) return; - switch (da2->crtcaddr) { - case LC_CRTC_OVERFLOW: - //return; - break; - case LC_MAXIMUM_SCAN_LINE: - if (!(da2->ioctl[LS_MODE] & 0x01)) val = 0; - break; - case LC_START_ADDRESS_HIGH: - //if (da2->crtc[0x1c] & 0x40) return; - break; - case LC_VERTICAL_TOTALJ: /* Vertical Total */ - case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ - case LC_V_DISPLAY_ENABLE_END: /* Vertical Display End Register */ - case LC_START_VERTICAL_BLANK: /* Start Vertical Blank Register */ - //val = 0x400; //for debugging bitblt - break; - case LC_VIEWPORT_SELECT: /* ViewPort Select? */ - //return; - break; - case LC_VIEWPORT_NUMBER: /* Compatibility? */ - break; - } - da2->crtc[da2->crtcaddr] = val; - switch (da2->crtcaddr) { - case LC_H_DISPLAY_ENABLE_END: - case LC_VERTICAL_TOTALJ: - case LC_MAXIMUM_SCAN_LINE: - case LC_START_ADDRESS_HIGH: - case LC_START_ADDRESS_LOW: - case LC_VERTICAL_SYNC_START: - case LC_V_DISPLAY_ENABLE_END: - case LC_START_VERTICAL_BLANK: - case LC_END_VERTICAL_BLANK: - case LC_VIEWPORT_PRIORITY: - da2->fullchange = changeframecount; - da2_recalctimings(da2); - break; - default: - break; - } - break; - case LV_PORT: - //da2_log("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc); - if (!da2->attrff) - { - // da2->attraddr = val & 31; - da2->attraddr = val & 0x3f; - if ((val & 0x20) != (da2->attr_palette_enable & 0x20)) - { - da2->fullchange = 3; - da2->attr_palette_enable = val & 0x20; - da2_recalctimings(da2); - } - //da2_log("set attraddr: %X\n", da2->attraddr); - } - else - { - if ((da2->attraddr == LV_PANNING) && (da2->attrc[LV_PANNING] != val)) - da2->fullchange = changeframecount; - if (da2->attrc[da2->attraddr & 0x3f] != val) - da2_log("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrc[da2->attraddr & 0x3f], val); - da2->attrc[da2->attraddr & 0x3f] = val; - //da2_log("set attrc %x: %x\n", da2->attraddr & 31, val); - if (da2->attraddr < 16) - da2->fullchange = changeframecount; - if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) - { - for (int c = 0; c < 16; c++) - { - //if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4); - //else da2->egapal[c] = (da2->attrc[c] & 0x3f) | ((da2->attrc[0x14] & 0xc) << 4); - if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = da2->attrc[c] & 0xf; - else da2->egapal[c] = da2->attrc[c] & 0x3f; - } - } - switch (da2->attraddr) - { - case LV_COLOR_PLANE_ENAB: - if ((val & 0xff) != da2->plane_mask) - da2->fullchange = changeframecount; - da2->plane_mask = val & 0xff; - break; - case LV_CURSOR_CONTROL: - switch (val & 0x18) { - case 0x08://fast blink - da2->blinkconf = 0x10; - break; - case 0x18://slow blink - da2->blinkconf = 0x20; - break; - default://no blink - da2->blinkconf = 0xff; - break; - } - break; - case LV_MODE_CONTROL: - case LV_ATTRIBUTE_CNTL: - case LV_COMPATIBILITY: - da2_recalctimings(da2); - break; - default: - break; - } - } - da2->attrff ^= 1; - break; - case 0x3E9: - /* VZ Editor's CURSOR.COM writes data via this port */ - da2->attrc[da2->attraddr & 0x3f] = val; - break; - case LG_INDEX: - da2->gdcaddr = val; - break; - case LG_DATA: - //if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); - //if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI); - switch (da2->gdcaddr & 0x1f) - { - case LG_READ_MAP_SELECT: - da2->readplane = val & 0x7; - break; - case LG_MODE: - da2->writemode = val & 3; - break; - case LG_MAP_MASKJ: - da2->writemask = val & 0xff; - break; - case LG_COMMAND: - break; - case LG_SET_RESET_2: - da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); - return; - } - da2->gdcreg[da2->gdcaddr & 15] = val & 0xff; - break; - //case 0x3ed: /* used by Windows 3.1 display driver */ - // da2->gdcreg[5] = val & 0xff; - // break; - default: - da2_log("DA2? Out addr %03X val %02X\n", addr, val); - break; - } -} - -uint16_t da2_in(uint16_t addr, void *p) -{ - da2_t * da2 = (da2_t *)p; - uint16_t temp; - - switch (addr) - { - case 0x3c3: - temp = 0; - break; - case 0x3c6: temp = da2->dac_mask; - break; - case 0x3c7: temp = da2->dac_status; - break; - case 0x3c8: temp = da2->dac_write; - break; - case 0x3c9: - da2->dac_status = 3; - switch (da2->dac_pos) - { - case 0: - da2->dac_pos++; - temp = da2->vgapal[da2->dac_read].r & 0x3f; - break; - case 1: - da2->dac_pos++; - temp = da2->vgapal[da2->dac_read].g & 0x3f; - break; - case 2: - da2->dac_pos = 0; - da2->dac_read = (da2->dac_read + 1) & 255; - temp = da2->vgapal[(da2->dac_read - 1) & 255].b & 0x3f; - break; - } - break; - case LS_INDEX: - temp = da2->ioctladdr; - break; - case LS_DATA: - //da2->ioctl[3] = 0x80;//3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) - if (da2->ioctladdr > 0xf) return DA2_INVALIDACCESS8; - temp = da2->ioctl[da2->ioctladdr]; - if (da2->ioctladdr == LS_STATUS) { /* Status register */ - if (da2->attrc[LV_COMPATIBILITY] & 0x08) { /* for detecting monitor type and cable wiring */ - if (da2->monitorid == DA2_DCONFIG_MONTYPE_MONO) { - /* grayscale monitor */ - if ((da2->vgapal[0].r >= 10) || (da2->vgapal[0].g >= 40) || (da2->vgapal[0].b >= 10)) - temp &= 0x7F; /* Inactive when the RGB output voltage is high (or the cable is not connected to a color monitor). */ - else - temp |= 0x80; /* Active when the RGB output voltage is low and the cable is connected to a color monitor. - If the cable or the monitor is wrong, it becomes inactive. */ - } else { - /* color monitor */ - if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 80) - temp &= 0x7F; - else - temp |= 0x80; - } - } else { - temp |= 0x80; - } - temp &= 0xf6;//clear busy bits - if (da2->bitblt.indata) /* for OS/2 J1.3 */ - da2_bitblt_dopayload(da2); - if (da2->bitblt.exec != DA2_BLT_CIDLE) - { - //da2_log("exec:%x\n", da2->bitblt.exec); - temp |= 0x08;//wait(bit 3 + bit 0) - //if (!da2->bitblt.timer.enabled) - //{ - // da2_log("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); - // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - //} - } - if (da2->bitblt.indata) - temp |= 0x01; - //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); - } - //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); - break; - case LF_INDEX: - temp = da2->fctladdr; - break; - case LF_DATA: - if (da2->fctladdr > 0x1f) return DA2_INVALIDACCESS8; - temp = da2->fctl[da2->fctladdr]; - break; - case LC_INDEX: - temp = da2->crtcaddr; - break; - case LC_DATA: - if (da2->crtcaddr > 0x1f) return DA2_INVALIDACCESS8; - temp = da2->crtc[da2->crtcaddr]; - break; - case LV_PORT: - temp = da2->attraddr | da2->attr_palette_enable; - break; - case 0x3E9: - if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this may equiv to 3ba / 3da Input Status Register 1 */ - { - if (da2->cgastat & 0x01) - da2->cgastat &= ~0x30; - else - da2->cgastat ^= 0x30; - temp = da2->cgastat; - } - else - temp = da2->attrc[da2->attraddr]; - //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->attraddr, temp, cs >> 4, cpu_state.pc); - da2->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */ - break; - case LG_INDEX: - temp = da2->gdcaddr; - break; - case LG_DATA: - temp = da2->gdcreg[da2->gdcaddr & 0x1f]; - //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc); - break; - } - //da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); - 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) -*/ -void da2_outb(uint16_t addr, uint8_t val, void* p) -{ - da2_t* da2 = (da2_t*)p; - //da2_log("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); - da2->inflipflop = 0; - switch (addr) - { - case LS_DATA: - case LF_DATA: - case LC_DATA: - case LG_DATA: - if (da2->outflipflop) - { - /* out b(idx), out b(data), out b(data) */ - da2->iolatch |= (uint16_t)val << 8; - da2->outflipflop = 0; - } - else - {// - da2->iolatch = val; - da2->outflipflop = 1; - } - break; - case LS_INDEX: - case LF_INDEX: - case LC_INDEX: - case LG_INDEX: - default: - da2->iolatch = val; - da2->outflipflop = 0; - break; - } - da2_out(addr, da2->iolatch, da2); -} -void da2_outw(uint16_t addr, uint16_t val, void* p) -{ - //da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - da2_t* da2 = (da2_t*)p; - da2->inflipflop = 0; - switch (addr) - { - case LS_INDEX: - case LF_INDEX: - case LC_INDEX: - case LG_INDEX: - da2_out(addr, val & 0xff, da2); - da2->iolatch = val >> 8; - da2_out(addr + 1, da2->iolatch, da2); - da2->outflipflop = 1; - break; - case LV_PORT: - da2->attrff = 0; - da2_out(addr, val & 0xff, da2); - da2_out(addr, val >> 8, da2); - da2->outflipflop = 0; - break; - case 0x3EC: - //da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - da2_out(LG_DATA, val >> 8, da2); - break; - case 0x3ED: - da2->gdcaddr = LG_MODE; - da2_out(LG_DATA, val, da2); - break; - case LS_DATA: - case LF_DATA: - case LC_DATA: - case LG_DATA: - default: - da2_out(addr, val, da2); - da2->outflipflop = 0; - break; - case 0x3EE: - da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - da2->reg3ee[val & 0xff] = val >> 8; - break; - } -} -uint8_t da2_inb(uint16_t addr, void* p) -{ - uint8_t temp; - da2_t* da2 = (da2_t*)p; - da2->outflipflop = 0; - switch (addr) - { - case LC_DATA: - if (da2->inflipflop) - { - /* out b(idx), in b(low data), in b(high data) */ - temp = da2->iolatch >> 8; - da2->inflipflop = 0; - } - else - {// - da2->iolatch = da2_in(addr, da2); - temp = da2->iolatch & 0xff; - da2->inflipflop = 1; - } - break; - case LS_INDEX: - case LF_INDEX: - case LC_INDEX: - case LG_INDEX: - case LS_DATA: - case LF_DATA: - case LG_DATA: - default: - temp = da2_in(addr, da2) & 0xff; - da2->inflipflop = 0; - break; - } - //da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); - return temp; -} -uint16_t da2_inw(uint16_t addr, void* p) -{ - //uint16_t temp; - da2_t* da2 = (da2_t*)p; - da2->inflipflop = 0; - da2->outflipflop = 0; - return da2_in(addr, da2); -} -/* IO 03DAh : Input Status Register 2 for DOSSHELL in DOS J4.0 */ -uint8_t da2_in_ISR(uint16_t addr, void* p) -{ - da2_t* da2 = (da2_t*)p; - uint8_t temp = 0; - if (addr == 0x3da) { - if (da2->cgastat & 0x01) - da2->cgastat &= ~0x30; - else - da2->cgastat ^= 0x30; - temp = da2->cgastat; - } - //da2_log("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); - return temp; -} - -void da2_out_ISR(uint16_t addr, uint8_t val, void* p) -{ - //da2_t* da2 = (da2_t*)p; - da2_log("DA2D Out %04X %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); -} - -/* -The IBM 5550 character mode addresses video memory between E0000h and E0FFFh. - [Character drawing] - SBCS: - 1 2 ... 13 - 1 | H.Grid - |---------------- - 2 | Space - 3 V| - .| - G| Font Pattern - r| (12x24 pixels) - i| - d| -26 |________________ -27 Space - ---------------- -28 Underscore ] - ---------------- >Cursor Position -29 ] - - DBCS: - 1 2 ... 13 1 2 ... 12 13 - 1 | H.Grid | H.Grid | - -|--------------------------|- - 2 | Space | Space | - -|--------------------------|- - 3 V| | |S - .| | |p - G| Font Pattern |a - r| (24x24 pixels) |c - i| | |e - d| | | -26 |_____________|____________| -27 | Space | Space - ------------------------------ -28 | Underscore | Underscore ] - ------------------------------ >Cursor Position -29 | | ] - - [Attributes] - Video mode 08h: - 7 6 5 4 3 2 1 0 - Blink |Under |HGrid |VGrid |Bright|Revers|FntSet|DBCS/SBCS| - - Video mode 0Eh: - -Blue |-Green|HGrid |VGrid |-Red |Revers|FntSet|DBCS/SBCS| - - Bit 1 switches the font bank to the Extended SBCS. DOS K3.x loads APL characters from $SYSEX24.FNT into it. - DOS Bunsho Program transfers 1/2 and 1/4 fonts fron the font ROM to the Extended SBCS. - This bit is not used for DBCS, but some apps set it as that column is right half of DBCS. - -[Font ROM Map (DA2, Japanese)] -The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh. - - Bank 0 - 4800- * - Bank 1, 2, 3 - * - * - Bank 4 - * -0DB6Fh ( 4800-8DB6Fh) : JIS X 0208 DBCS (24 x 24) (IBMJ code: 100-1F7Dh) - 10000-16D1Fh (90000-96D1Fh) : IBM Extended Characters (IBMJ code: 2ADC-2C5Fh) - 18000-1BFCFh (98000-9BFCFh) : JIS X 0201 SBCS (13 x 30) - 1C000-1FFFFh (9C000-9FFFFh) : Codepage 437 characters (13 x 30) - Bank 5 - 00000-0C68Fh (A0000-AC68Fh) : Gaiji used by DOS Bunsho - 10000-13FFFh (B0000-B3FFFh) : Extended SBCS (13 x 30) - 14000-1477Fh (B4000-B477Fh) : Half-width box drawing characters used by DOS Bunsho - 16000-17FFFh (B6000-B7FFFh) : Codepage 850 characters (13 x 30) - 18000-1A3FFh (B8000-BA3FFh) : CAD control icons and box drawing characters (32 x 32) - - Some models have the signature 80h, 01h placed at Bank 0:1AFFEh. (it disables hardware text drawing in OS/2 J1.3) - -[Font ROM Map (DA3, Traditional Chinese)] - Bank 0 - 11 : Valid Font ROM data - Bank 12 : Alias of bank 11 (At least, DOS T5.0 uses this on purpose.) - Bank 13 : All addresses return 0xFF - -[Gaiji RAM Map (DA2)] - Bank 0 00000-1FFFFh placed between A0000h-BFFFFh - 00000-1F7FFh(A0000-BF7FFh): Gaiji Non-resident (Kuten 103-114 ku,IBM: 2674-2ADBh) 1008 chs 128 bytes - 1F800-1FFFFh(BF800-BFFFFh): Gaiji Resident (SJIS: F040-F04Fh, IBM: 2384-2393h) 16 chs - - Bank 1 20000-3FFFFh placed between A0000h-BFFFFh - 20000-33FFFh(A0000-B3FFFh): Gaiji Resident (SJIS: F050-F39Ch, IBM: 2394-2613h) 640 chs - 34000-37FFFh(B4000-B7FFFh): Basic SBCS(00-FFh, ATTR bit 1 = off) - 38000-3AFFFh(B8000-BAFFFh): Gaiji Resident (SJIS: F39D-F3FCh, IBM: 2614-2673h) 96 chs - 3C000-3FFFFh(BC000-BFFFFh): Extended SBCS(00-FFh, ATTR bit 1 = on) - -[IBMJ code to Gaiji address conv tbl from DOS K3.3] - A B C - 2ADC, 2C5F, +5524 --> 8000 - 2614, 2673, +90EC --> B700 - 2384, 2613, +906C --> B3F0 - 0682, 1F7D, +0000 - - 8000 - 8183h 184h(388 characters) IBM Extended Characters - B3F0 - B75Fh 370h(880 characters) User-defined Characters -*/ - -/* Get character line pattern from jfont rom or gaiji volatile memory */ -uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void* p) { - da2_t* da2 = (da2_t*)p; - uint32_t font = 0; - int32_t fline = line - 2;//Start line of drawing character (line >= 1 AND line < 24 + 1 ) - if (code >= 0x8000 && code <= 0x8183) code -= 0x6000;//shift for IBM extended characters (I don't know how the real card works.) - if (code < DA2_FONTROM_SIZE / 72 && fline >= 0 && fline < 24) { - font = da2->mmio.font[code * 72 + fline * 3]; //1111 1111 - font <<= 8; //1111 1111 0000 0000 - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; //1111 1111 2222 0000 - font >>= 1; //0111 1111 1222 2000 - font <<= 4; //0111 1111 1222 2000 0000 - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; //0111 1111 1222 2000 2222 - font <<= 8; //0111 1111 1222 2000 2222 0000 0000 - font |= da2->mmio.font[code * 72 + fline * 3 + 2]; //0111 1111 1222 2000 2222 3333 3333 - font <<= 4; //0111 1111 1222 2000 2222 3333 3333 0000 - //font >>= 1;//put blank at column 1 (and 26) - } - else if (code >= 0xb000 && code <= 0xb75f) - { - //convert code->address in gaiji memory - code -= 0xb000; - code *= 0x80; - //code += 0xf800; - font = da2->mmio.ram[code + line * 4]; - font <<= 8; - font |= da2->mmio.ram[code + line * 4 + 1]; - font <<= 8; - font |= da2->mmio.ram[code + line * 4 + 2]; - font <<= 8; - font |= da2->mmio.ram[code + line * 4 + 3]; - } - else if (code > DA2_FONTROM_SIZE) - font = 0xffffffff; - else - font = 0; - return font; -} - -/* Reverse the bit order of attribute code IRGB to BGRI(used in Mode 3 and Cursor Color) */ -uint8_t IRGBtoBGRI(uint8_t attr) -{ - attr = ((attr & 0x01) << 7) | ((attr & 0x02) << 5) | ((attr & 0x04) << 3) | ((attr & 0x08) << 1); - return attr >>= 4; -} -/* Get the foreground color from the attribute byte */ -uint8_t getPS55ForeColor(uint8_t attr, da2_t* da2) -{ - uint8_t foreground = ~attr & 0x08;// 0000 1000 - foreground <<= 2; //0010 0000 - foreground |= ~attr & 0xc0;// 1110 0000 - foreground >>= 4;//0000 1110 - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;//bright color palette - return foreground; -} - -void da2_render_blank(da2_t* da2) -{ - int x, xx; - - if (da2->firstline_draw == 2000) - da2->firstline_draw = da2->displine; - da2->lastline_draw = da2->displine; - - for (x = 0; x < da2->hdisp; x++) - { - for (xx = 0; xx < 13; xx++) ((uint32_t*)buffer32->line[da2->displine])[(x * 13) + xx + 32] = 0; - } -} -/* Display Adapter Mode 8, E Drawing */ -static void da2_render_text(da2_t* da2) -{ - if (da2->firstline_draw == 2000) - da2->firstline_draw = da2->displine; - da2->lastline_draw = da2->displine; - - if (da2->fullchange) - { - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - int x; - int drawcursor; - uint8_t chr, attr; - int fg, bg; - uint32_t chr_dbcs; - int chr_wide = 0; - //da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); - for (x = 0; x < da2->hdisp; x += 13) - { - chr = da2->cram[(da2->ma) & da2->vram_display_mask]; - attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; - //if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80)//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, da2); - 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 = ((da2->blink & 0x20) || (!(attr & 0x80))) ? fg : bg; - //if(chr!=0x20) da2_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, da2->egapal[fg], da2->pallook[da2->egapal[fg]]); - } - //Draw character - for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->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 = da2->cram[((da2->ma) + 2) & da2->vram_display_mask]; - chr_dbcs <<= 8; - chr_dbcs |= chr; - // Get the font pattern - uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots - for (uint32_t n = 0; n < 13; n++) { - p[n] = da2->pallook[da2->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 = DA2_GAIJIRAM_SBEX; - else - fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font - font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font - //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); - // Draw 13 dots - for (uint32_t n = 0; n < 13; n++) { - p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; - font <<= 1; - } - } - } - // right half of DBCS - else - { - uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots - for (uint32_t n = 0; n < 13; n++) { - p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; - font <<= 1; - } - chr_wide = 0; - } - //Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. - if (da2->sc == 27 && attr & 0x40 && ~da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) {//Underscore only in monochrome mode - for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[fg]];//under line (white) - } - //Column 1 (Vertical Line) - if (attr & 0x10) { - p[0] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];//vertical line (white) - } - if (da2->sc == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) {//HGrid - for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];//horizontal line (white) - } - //Drawing text cursor - drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); - if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) - { - int cursorwidth = (da2->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); - int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2;//Choose color 2 if mode 8 - fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : ((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] == da2->pallook[da2->egapal[cursorcolor]] || da2->egapal[bg] == da2->egapal[cursorcolor]) - p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[fg]] : da2->pallook[da2->egapal[bg]]; - else - p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[cursorcolor]] : p[n]; - } - da2->ma += 2; - p += 13; - } - da2->ma &= da2->vram_display_mask; - //da2->writelines++; - } -} - -/* Display Adapter Mode 3 Drawing */ -static void da2_render_textm3(da2_t* da2) -{ - if (da2->firstline_draw == 2000) - da2->firstline_draw = da2->displine; - da2->lastline_draw = da2->displine; - - if (da2->fullchange) - { - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - int x; - int drawcursor; - uint8_t chr, attr, extattr; - int fg, bg; - uint32_t chr_dbcs; - int chr_wide = 0; - //da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); - for (x = 0; x < da2->hdisp; x += 13) - { - chr = da2->vram[(0x18000 + (da2->ma)) & da2->vram_mask]; - attr = da2->vram[((0x18000 + (da2->ma)) + 1) & da2->vram_mask]; - extattr = da2->vram[((0x10000 + (da2->ma)) + 1) & da2->vram_mask]; - //if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (0x18000 + da2->ma << 1) & da2->vram_mask, chr, attr); - bg = attr >> 4; - //if (da2->blink) bg &= ~0x8; - //fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg; - fg = attr & 0xf; - fg = IRGBtoBGRI(fg); - bg = IRGBtoBGRI(bg); - //Draw character - for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank - // SBCS or DBCS left half - if (chr_wide == 0) { - if (extattr & 0x01) chr_wide = 1; - // 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 = da2->vram[(0x18000 + (da2->ma) + 2) & da2->vram_mask]; - chr_dbcs <<= 8; - chr_dbcs |= chr; - // Get the font pattern - uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots - for (uint32_t n = 0; n < 13; n++) { - p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; - font <<= 1; - } - } - else { - // the char code is SBCS (ANK) - uint32_t fontbase; - fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font - font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font - //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); - for (uint32_t n = 0; n < 13; n++) { - p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; - font <<= 1; - } - } - } - // right half of DBCS - else - { - uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots - for (uint32_t n = 0; n < 13; n++) { - p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; - font <<= 1; - } - chr_wide = 0; - } - //Drawing text cursor - drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); - if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) - { - //int cursorwidth = (da2->crtc[0x1f] & 0x20 ? 26 : 13); - //int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;//Choose color 2 if mode 8 - //fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; - //bg = 0; - //if (attr & 0x04) {//Color 0 if reverse - // bg = fg; - // fg = 0; - //} - for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[fg]]; - } - da2->ma += 2; - p += 13; - } - da2->ma &= da2->vram_display_mask; - //da2->writelines++; - } -} - -void da2_render_color_4bpp(da2_t* da2) -{ - int changed_offset = da2->ma >> 12; - //da2_log("ma %x cf %x\n", da2->ma, changed_offset); - da2->plane_mask &= 0x0f;//safety - - if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) - { - int x; - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - - if (da2->firstline_draw == 2000) - da2->firstline_draw = da2->displine; - da2->lastline_draw = da2->displine; - //da2_log("d %X\n", da2->ma); - - for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 - { - uint8_t edat[8]; - uint8_t dat; - - //get 8 pixels from vram - da2->ma &= da2->vram_display_mask; - *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); - da2->ma += 1; - - dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)); - p[0] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)); - p[1] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)); - p[2] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)); - p[3] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)); - p[4] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)); - p[5] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)); - p[6] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)); - p[7] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - p += 8; - } - //da2->writelines++; - } -} - -void da2_render_color_8bpp(da2_t* da2) -{ - int changed_offset = da2->ma >> 12; - //da2_log("ma %x cf %x\n", da2->ma, changed_offset); - - if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) - { - int x; - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - - if (da2->firstline_draw == 2000) - da2->firstline_draw = da2->displine; - da2->lastline_draw = da2->displine; - //da2_log("d %X\n", da2->ma); - - for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 - { - uint8_t edat[8]; - uint8_t dat; - - //get 8 pixels from vram - da2->ma &= da2->vram_display_mask; - *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); - *(uint32_t*)(&edat[4]) = *(uint32_t*)(&da2->vram[(da2->ma << 3) + 4]); - da2->ma += 1; - - dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)) | - ((edat[4] >> 3) & (1 << 4)) | ((edat[5] >> 2) & (1 << 5)) | ((edat[6] >> 1) & (1 << 6)) | ((edat[7] >> 0) & (1 << 7)); - p[0] = da2->pallook[dat]; - dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)) | - ((edat[4] >> 2) & (1 << 4)) | ((edat[5] >> 1) & (1 << 5)) | ((edat[6] >> 0) & (1 << 6)) | ((edat[7] << 1) & (1 << 7)); - p[1] = da2->pallook[dat]; - dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)) | - ((edat[4] >> 1) & (1 << 4)) | ((edat[5] >> 0) & (1 << 5)) | ((edat[6] << 1) & (1 << 6)) | ((edat[7] << 2) & (1 << 7)); - p[2] = da2->pallook[dat]; - dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)) | - ((edat[4] >> 0) & (1 << 4)) | ((edat[5] << 1) & (1 << 5)) | ((edat[6] << 2) & (1 << 6)) | ((edat[7] << 3) & (1 << 7)); - p[3] = da2->pallook[dat]; - dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)) | - ((edat[4] << 1) & (1 << 4)) | ((edat[5] << 2) & (1 << 5)) | ((edat[6] << 3) & (1 << 6)) | ((edat[7] << 4) & (1 << 7)); - p[4] = da2->pallook[dat]; - dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)) | - ((edat[4] << 2) & (1 << 4)) | ((edat[5] << 3) & (1 << 5)) | ((edat[6] << 4) & (1 << 6)) | ((edat[7] << 5) & (1 << 7)); - p[5] = da2->pallook[dat]; - dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)) | - ((edat[4] << 3) & (1 << 4)) | ((edat[5] << 4) & (1 << 5)) | ((edat[6] << 5) & (1 << 6)) | ((edat[7] << 6) & (1 << 7)); - p[6] = da2->pallook[dat]; - dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)) | - ((edat[4] << 4) & (1 << 4)) | ((edat[5] << 5) & (1 << 5)) | ((edat[6] << 6) & (1 << 6)) | ((edat[7] << 7) & (1 << 7)); - p[7] = da2->pallook[dat]; - p += 8; - } - //da2->writelines++; - } -} - -void da2_updatevidselector(da2_t* da2) { - /* if VGA passthrough mode */ - da2_log("DA2 selector: %d\n", da2->ioctl[LS_MODE]); - if (da2->ioctl[LS_MODE] & 0x02) - { - da2->override = 1; - svga_set_override(da2->mb_vga, 0); - } - else - { - svga_set_override(da2->mb_vga, 1); - da2->override = 0; - } -} - -void da2_recalctimings(da2_t* da2) -{ - double crtcconst; - double _dispontime, _dispofftime, disptime; - - da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff;//w - da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff;//w - da2->vsyncstart = da2->crtc[LC_VERTICAL_SYNC_START] & 0xfff;//w - da2->split = da2->crtc[LC_LINE_COMPAREJ] & 0xfff;//w Line Compare - da2->split = 0xfff; - da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff;//w - da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; - - if (da2->crtc[LC_START_H_DISPLAY_ENAB] & 1) { - da2->hdisp--; - da2->dispend -= 29; - } - else { - //da2->vtotal += 2; - da2->dispend--; - //da2->vsyncstart++; - //da2->split++; - //da2->vblankstart++; - //da2->hdisp--; - } - - da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; - da2->htotal += 1; - - da2->rowoffset = da2->crtc[LC_OFFSET];//number of bytes in a scanline - - da2->clock = da2->da2const; - - //da2->lowres = da2->attrc[LV_MODE_CONTROL] & 0x40; - - //da2->interlace = 0; - - //da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b - da2->ca_adj = 0; - - da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE]; - - da2->hdisp_time = da2->hdisp; - da2->render = da2_render_blank; - //determine display mode - //if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) - if (da2->attrc[LV_COMPATIBILITY] & 0x08) - { - if (!(da2->ioctl[LS_MODE] & 0x01)) {//16 color graphics mode - da2->hdisp *= 16; - da2->char_width = 13; - da2->hdisp_old = da2->hdisp; - if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) { - da2_log("Set videomode to PS/55 8 bpp graphics.\n"); - da2->render = da2_render_color_8bpp; - da2->vram_display_mask = DA2_MASK_GRAM; - } - else {//PS/55 8-color - da2_log("Set videomode to PS/55 4 bpp graphics.\n"); - da2->vram_display_mask = DA2_MASK_GRAM; - da2->render = da2_render_color_4bpp; - } - } - else {//text mode - if (da2->attrc[LV_ATTRIBUTE_CNTL] & 1) { - da2_log("Set videomode to PS/55 Mode 03 text.\n"); - da2->render = da2_render_textm3; - da2->vram_display_mask = DA2_MASK_CRAM; - } - else {//PS/55 text(color/mono) - da2_log("Set videomode to PS/55 Mode 8/E text.\n"); - da2->render = da2_render_text; - da2->vram_display_mask = DA2_MASK_CRAM; - } - da2->hdisp *= 13; - da2->hdisp_old = da2->hdisp; - da2->char_width = 13; - } - } - else - { - da2_log("Set videomode to blank.\n"); - } - //if (!da2->scrblank && da2->attr_palette_enable) - //{ - //da2->render = da2_draw_text; - //} - - // da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); - - //if (da2->recalctimings_ex) - // da2->recalctimings_ex(da2); - - if (da2->vblankstart < da2->dispend) - da2->dispend = da2->vblankstart; - - crtcconst = da2->clock * da2->char_width; - - disptime = da2->htotal; - _dispontime = da2->hdisp_time; - - da2_log("Disptime %f dispontime %f hdisp %i\n", disptime, _dispontime, da2->hdisp); - //if (da2->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; } - _dispofftime = disptime - _dispontime; - _dispontime *= crtcconst; - _dispofftime *= crtcconst; - - da2->dispontime = (uint64_t)_dispontime; - da2->dispofftime = (uint64_t)_dispofftime; - if (da2->dispontime < TIMER_USEC) - da2->dispontime = TIMER_USEC; - if (da2->dispofftime < TIMER_USEC) - da2->dispofftime = TIMER_USEC; - da2_log("da2 horiz total %i display end %i vidclock %f\n",da2->crtc[0],da2->crtc[1],da2->clock); - // da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart); - // da2_log("total %f on %i cycles off %i cycles frame %i sec %i\n",disptime*crtcconst,da2->dispontime,da2->dispofftime,(da2->dispontime+da2->dispofftime)*da2->vtotal,(da2->dispontime+da2->dispofftime)*da2->vtotal*70); - - // da2_log("da2->render %08X\n", da2->render); -} - -uint8_t da2_mca_read(int port, void *p) -{ - da2_t *da2 = (da2_t *)p; - return da2->pos_regs[port & 7]; -} - -static void da2_mapping_update(da2_t *da2) -{ - if (!((da2->pos_regs[2] ^ da2->old_pos2) & 1)) return; - da2->old_pos2 = da2->pos_regs[2]; - //da2_recalc_mapping(da2); - if (da2->pos_regs[2] & 0x01) - { - da2_log("DA2 enable registers\n"); - for (int i = 0; i < 8; i++) - da2_log("DA2 POS[%d]: %x\n", i, da2->pos_regs[i]); - io_sethandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); - io_sethandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); - io_sethandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); - mem_mapping_enable(&da2->cmapping); - mem_mapping_enable(&da2->mmio.mapping); - timer_enable(&da2->timer); - } - else - { - da2_log("DA2 disable registers\n"); - timer_disable(&da2->timer); - mem_mapping_disable(&da2->cmapping); - mem_mapping_disable(&da2->mmio.mapping); - io_removehandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); - io_removehandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); - io_removehandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); - } -} - -void da2_mca_write(int port, uint8_t val, void *p) -{ - da2_t *da2 = (da2_t *)p; - - da2_log("da2_mca_write: port=%04x val=%02x\n", port, val); - - if (port < 0x102) - return; - da2->pos_regs[port & 7] = val; - - da2_mapping_update(da2); -} - -static uint8_t da2_mca_feedb(void* priv) -{ - const da2_t* da2 = (da2_t*)priv; - - return da2->pos_regs[2] & 0x01; -} - -static void da2_mca_reset(void *p) -{ - da2_t *da2 = (da2_t *)p; - da2_reset(da2); - da2_mca_write(0x102, 0, da2); -} -// -static void da2_gdcropB(uint32_t addr, da2_t* da2) { - for (int i = 0; i < 8; i++) { - if (da2->writemask & (1 << i)) { - //da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW]); - switch (da2->gdcreg[LG_COMMAND] & 0x03) - { - case 0: /*Set*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - case 1: /*AND*/ - //da2->vram[addr | i] = (da2->gdcinput[i] | ~da2->gdcreg[LG_BIT_MASK_LOW]) & da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - case 2: /*OR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - case 3: /*XOR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) ^ da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - } - } - } -} -static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t* da2) { - uint8_t bitmask_l = bitmask & 0xff; - uint8_t bitmask_h = bitmask >> 8; - for (int i = 0; i < 8; i++) { - if (da2->writemask & (1 << i)) { - //da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]); - switch (da2->gdcreg[LG_COMMAND] & 0x03) - { - case 0: /*Set*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l); - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h); - da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - case 1: /*AND*/ - //da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i]; - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - case 2: /*OR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i]; - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - case 3: /*XOR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i]; - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - } - } - } -} - -static uint8_t da2_mmio_read(uint32_t addr, void* p) -{ - da2_t* da2 = (da2_t*)p; - addr &= DA2_MASK_MMIO; - - if (da2->ioctl[LS_MMIO] & 0x10) { - if (da2->fctl[LF_MMIO_SEL] == 0x80) - //linear access - addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17); - else - { - //64k bank switch access - uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; - index <<= 8; - index |= da2->fctl[LF_MMIO_ADDR]; - addr += index * 0x40; - } - //da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); - switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { - case 0xb0://Gaiji RAM - addr &= DA2_MASK_GAIJIRAM;//safety access - //da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]); - return da2->mmio.ram[addr]; - break; - case 0x10://Font ROM - if (da2->mmio.charset == DA2_DCONFIG_CHARSET_HANT) { - if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; - if (addr >= 0x180000) addr -= 0x40000; /* The bank 12 (180000h-19ffffh) is beyond the available ROM address range, - but the Chinese font sub card actually has this alias, and is used by DOS T5.0. */ - } - if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; - //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); - return da2->mmio.font[addr]; - break; - default: - return DA2_INVALIDACCESS8;//invalid memory access - break; - } - } - else if (!(da2->ioctl[LS_MODE] & 1))//8 or 256 color mode - { - cycles -= video_timing_read_b; - for (int i = 0; i < 8; i++) - da2->gdcla[i] = da2->vram[(addr << 3) | i];//read in byte - //da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); - if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 - uint8_t ret = 0; - - for (int i = 0; i < 8; i++) - { - if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register - ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xff : 0); - } - return ~ret; - } - else return da2->gdcla[da2->readplane]; - } - else //text mode 3 - { - cycles -= video_timing_read_b; - return da2->vram[addr]; - } -} -static uint16_t da2_mmio_readw(uint32_t addr, void* p) -{ - da2_t* da2 = (da2_t*)p; - da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); - if (da2->ioctl[LS_MMIO] & 0x10) { - return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); - } - else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode - { - cycles -= video_timing_read_w; - addr &= DA2_MASK_MMIO; - for (int i = 0; i < 8; i++) - da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read vram into latch - -#ifdef ENABLE_DA2_DEBUGBLT - ////debug - //if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) - //{ - // fprintf(da2->mmrdbg_fp, "\nR %x ", addr); - // for (int i = 0; i <= 0xb; i++) - // fprintf(da2->mmrdbg_fp, "%02x ", da2->gdcreg[i]); - //} - //for (int i = 0; i < 16; i++) - //{ - // int pixeldata = 0; - // if (da2->gdcla[da2->readplane] & (1 << (15 - i))) pixeldata = 1; - // fprintf(da2->mmrdbg_fp, "%X", pixeldata); - //} - //da2->mmrdbg_vidaddr = addr; -#endif - - if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 - uint16_t ret = 0; - - for (int i = 0; i < 8; i++) - { - if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register - ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xffff : 0); - } - return ~ret; - } - else - { - //da2_log("da2_Rw: %05x=%04x\n", addr, da2->gdcla[da2->readplane]); - return da2->gdcla[da2->readplane]; - } - } - else { - return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); - } -} - -static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) -{ - da2_t* da2 = (da2_t*)p; - //da2_log("da2_mmio_write %x %x\n", addr, val); - if ((addr & ~DA2_MASK_MMIO) != 0xA0000) return; - addr &= DA2_MASK_MMIO; - - if (da2->ioctl[LS_MMIO] & 0x10) { - //if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI); - //Gaiji RAM - if (da2->fctl[LF_MMIO_SEL] == 0x80) - addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17);//xxxy yyyy yyyy yyyy yyyy - else - { - uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; - index <<= 8; - index |= da2->fctl[LF_MMIO_ADDR]; - addr += index * 0x40; - } - switch (da2->fctl[LF_MMIO_MODE]) { - case 0xb0://Gaiji RAM 1011 0000 - addr &= DA2_MASK_GAIJIRAM;//safety access - da2->mmio.ram[addr] = val; - break; - case 0x10://Font ROM 0001 0000 - //Read-Only - break; - case 0x00: - //da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - //addr &= 0x7f;//OS/2 write addr 1cf80-1cfc3, val xx - //if (addr >= DA2_BLT_MEMSIZE) - //{ - // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - // return; - //} - da2->bitblt.indata = 1; - if(da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) - da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - da2->bitblt.payload[da2->bitblt.payload_addr] = val; - da2->bitblt.payload_addr++; - break; - default: - da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - break; - } - } - else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode - { - uint8_t wm = da2->writemask; - //da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); -#ifdef ENABLE_DA2_DEBUGBLT - //debug - //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) - //{ - if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) - { - fprintf(da2->mmdbg_fp, "\nB %x ", addr); - for (int i = 0; i <= 0xb; i++) - fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); - } - for (int i = 0; i < 8; i++) - { - int pixeldata = 0; - if (val & (1 << (7 - i))) pixeldata = (da2->writemask & 0xf); - fprintf(da2->mmdbg_fp, "%X", pixeldata); - } - da2->mmdbg_vidaddr = addr; - //} -#endif - - cycles -= video_timing_write_b; - - da2->changedvram[addr >> 12] = changeframecount; - addr <<= 3; - - for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch - - //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); - //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); - - if (!(da2->gdcreg[LG_COMMAND] & 0x08)) - { - for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; - else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; - else da2->gdcinput[i] = val; - da2_gdcropB(addr, da2); - return; - } - - switch (da2->writemode) - { - case 2: - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) da2->vram[addr | i] = da2->gdcsrc[i]; - break; - case 0: - if (da2->gdcreg[LG_DATA_ROTATION] & 7) - val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - if (da2->gdcreg[LG_BIT_MASK_LOW] == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) da2->vram[addr | i] = val; - } - else - { - for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; - else da2->gdcinput[i] = val; - - for (int i = 0; i < 8; i++) - da2->debug_vramold[i] = da2->vram[addr | i];//use latch - da2_gdcropB(addr, da2); - //for (int i = 0; i < 8; i++) - // da2_log("\tsrc %02x in %02x bitm %02x mod %x rop %x: %02x -> %02x\n", da2->gdcsrc[i], da2->gdcinput[i], da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch - //// da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); - } - break; - case 1: - if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - } - else - { - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); - da2_gdcropB(addr, da2); - } - break; - case 3: - if (da2->gdcreg[LG_DATA_ROTATION] & 7) - val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - wm = da2->gdcreg[LG_BIT_MASK_LOW]; - da2->gdcreg[LG_BIT_MASK_LOW] &= val; - - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; - da2_gdcropB(addr, da2); - da2->gdcreg[LG_BIT_MASK_LOW] = wm; - break; - } - //da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); - } - else// mode 3h text - { - cycles -= video_timing_write_b; - da2->vram[addr] = val; - da2->fullchange = 2; - } -} -uint16_t rightRotate(uint16_t data, uint8_t count) -{ - return (data >> count) | (data << (sizeof(data) * 8 - count)); -} -static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) -{ - da2_t* da2 = (da2_t*)p; - uint8_t wm = da2->writemask; - uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; - bitmask <<= 8; - bitmask |= (uint16_t)da2->gdcreg[LG_BIT_MASK_LOW]; -#ifdef ENABLE_DA2_DEBUGBLT - //debug - //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) - //{ - if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) - { - fprintf(da2->mmdbg_fp, "\nW %x ", addr); - for (int i = 0; i <= 0xb; i++) - fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); - } - for (int i = 0; i < 16; i++) - { - int pixeldata = 0; - if (val & (1 << (15 - i))) pixeldata = (da2->writemask & 0xf); - fprintf(da2->mmdbg_fp, "%X", pixeldata); - } - da2->mmdbg_vidaddr = addr; - //} -#endif - cycles -= video_timing_write_w; - //cycles_lost += video_timing_write_w; - - //da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); - //da2_log("da2_gcW %05X %02X %04X:%04X esdi %04X:%04X dssi %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); - - da2->changedvram[addr >> 12] = changeframecount; - da2->changedvram[(addr + 1) >> 12] = changeframecount; - addr <<= 3; - - for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch - - if (!(da2->gdcreg[LG_COMMAND] & 0x08)) - { - for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; - else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; - else da2->gdcinput[i] = val; - da2_gdcropW(addr, bitmask, da2); - return; - } - //da2_log("da2_Ww m%02x r%02x %05x:%04x=%02x%02x%02x%02x,%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] - // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); - switch (da2->writemode) - { - case 2: - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) - { - da2->vram[addr | i] = da2->gdcsrc[i] & 0xff; - da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; - } - break; - case 0: - if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work - if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) - { - da2->vram[addr | i] = val & 0xff; - da2->vram[(addr + 8) | i] = val >> 8; - } - } - else - { - for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; - else da2->gdcinput[i] = val; - da2_gdcropW(addr, bitmask, da2); - // da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); - } - break; - case 1: - if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) - { - uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); - da2->vram[addr | i] = wdata & 0xff; - da2->vram[(addr + 8) | i] = wdata >> 8; - } - } - else - { - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); - da2_gdcropW(addr, bitmask, da2); - } - break; - case 3: - if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work - wm = bitmask; - bitmask &= val; - - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; - da2_gdcropW(addr, bitmask, da2); - bitmask = wm; - break; - } - //da2_log("%02x%02x%02x%02x,%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] - // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); -} -static void da2_mmio_writew(uint32_t addr, uint16_t val, void* p) -{ - da2_t* da2 = (da2_t*)p; - //if ((addr & ~0x1ffff) != 0xA0000) return; - if (da2->ioctl[LS_MMIO] & 0x10) { - //da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); - da2_mmio_write(addr, val & 0xff, da2); - da2_mmio_write(addr + 1, val >> 8, da2); - } - else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode - { - addr &= DA2_MASK_MMIO; - //return; - //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); - da2_mmio_gc_writeW(addr, val, da2); - } - else {//mode 3h text - //if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); - da2_mmio_write(addr, val & 0xff, da2); - da2_mmio_write(addr + 1, val >> 8, da2); - } -} - -static void da2_code_write(uint32_t addr, uint8_t val, void* p) -{ - da2_t* da2 = (da2_t*)p; - //if ((addr & ~0xfff) != 0xE0000) return; - addr &= DA2_MASK_CRAM; - da2->cram[addr] = val; - da2->fullchange = 2; -} -static void da2_code_writeb(uint32_t addr, uint8_t val, void* p) -{ - da2_t* da2 = (da2_t*)p; - //da2_log("DA2_code_writeb: Write to %x, val %x\n", addr, val); - cycles -= video_timing_write_b; - da2_code_write(addr, val, da2); -} -static void da2_code_writew(uint32_t addr, uint16_t val, void* p) -{ - //da2_log("DA2_code_writew: Write to %x, val %x\n", addr, val); - da2_t* da2 = (da2_t*)p; - cycles -= video_timing_write_w; - da2_code_write(addr, val & 0xff, da2); - da2_code_write(addr + 1, val >> 8, da2); -} - -static uint8_t da2_code_read(uint32_t addr, void* p) -{ - da2_t* da2 = (da2_t*)p; - if ((addr & ~DA2_MASK_CRAM) != 0xE0000) return DA2_INVALIDACCESS8; - addr &= DA2_MASK_CRAM; - return da2->cram[addr]; -} -static uint8_t da2_code_readb(uint32_t addr, void* p) -{ - da2_t* da2 = (da2_t*)p; - cycles -= video_timing_read_b; - return da2_code_read(addr, da2); -} -static uint16_t da2_code_readw(uint32_t addr, void* p) -{ - da2_t* da2 = (da2_t*)p; - cycles -= video_timing_read_w; - return da2_code_read(addr, da2) | (da2_code_read(addr + 1, da2) << 8); - //return 0; -} - -void da2_doblit(int y1, int y2, int wx, int wy, da2_t* da2) -{ - 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; -} - -void da2_poll(void* priv) -{ - da2_t* da2 = (da2_t*)priv; - int x; - - if (!da2->linepos) - { - timer_advance_u64(&da2->timer, da2->dispofftime); - // if (output) printf("Display off %f\n",vidtime); - da2->cgastat |= 1; - da2->linepos = 1; - - if (da2->dispon) - { - da2->hdisp_on = 1; - - da2->ma &= da2->vram_display_mask; - if (da2->firstline == 2000) - { - da2->firstline = da2->displine; - video_wait_for_buffer(); - } - - if (!da2->override) - da2->render(da2); - - if (da2->lastline < da2->displine) - da2->lastline = da2->displine; - } - - //da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); - da2->displine++; - //if (da2->interlace) - // da2->displine++; - if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) - { - //da2_log("Vsync off at line %i\n",displine); - da2->cgastat &= ~8; - } - da2->vslines++; - if (da2->displine > 1200) - da2->displine = 0; - // da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], - // displine, vc, ma); - } - else - { - // da2_log("VC %i ma %05X\n", da2->vc, da2->ma); - timer_advance_u64(&da2->timer, da2->dispontime); - - // if (output) printf("Display on %f\n",vidtime); - if (da2->dispon) - da2->cgastat &= ~1; - da2->hdisp_on = 0; - - da2->linepos = 0; - if (da2->sc == (da2->crtc[LC_CURSOR_ROW_END] & 31)) - da2->con = 0; - if (da2->dispon) - { - if (da2->sc == da2->rowcount) - { - da2->linecountff = 0; - da2->sc = 0; - - da2->maback += (da2->rowoffset << 1);// color = 0x50(80), mono = 0x40(64) - if (da2->interlace) - da2->maback += (da2->rowoffset << 1); - da2->maback &= da2->vram_display_mask; - da2->ma = da2->maback; - } - else - { - da2->sc++; - da2->sc &= 31; - da2->ma = da2->maback; - } - } - - da2->vc++; - da2->vc &= 2047; - - if (da2->vc == da2->dispend) - { - da2->dispon = 0; - //if (da2->crtc[10] & 0x20) da2->cursoron = 0; - //else da2->cursoron = da2->blink & 16; - if (da2->ioctl[LS_MODE] & 1) {//in text mode - if (da2->attrc[LV_CURSOR_CONTROL] & 0x01)//cursor blinking - { - da2->cursoron = (da2->blink | 1) & da2->blinkconf; - } - else - { - da2->cursoron = 0; - } - if (!(da2->blink & (0x10 - 1)))//force redrawing for cursor and blink attribute - da2->fullchange = 2; - } - da2->blink++; - - for (x = 0; x < ((da2->vram_mask + 1) >> 12); x++) - { - if (da2->changedvram[x]) - da2->changedvram[x]--; - } - // memset(changedvram,0,2048); del - if (da2->fullchange) - { - da2->fullchange--; - } - } - if (da2->vc == da2->vsyncstart) - { - int wx, wy; - // da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); - da2->dispon = 0; - da2->cgastat |= 8; - x = da2->hdisp; - - //if (da2->interlace && !da2->oddeven) da2->lastline++; - //if (da2->interlace && da2->oddeven) da2->firstline--; - - wx = x; - wy = da2->lastline - da2->firstline; - - da2_doblit(da2->firstline_draw, da2->lastline_draw + 1, wx, wy, da2); - - da2->firstline = 2000; - da2->lastline = 0; - - da2->firstline_draw = 2000; - da2->lastline_draw = 0; - - da2->oddeven ^= 1; - - changeframecount = da2->interlace ? 3 : 2; - da2->vslines = 0; - - //if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch + (da2->rowoffset << 1) + ((da2->crtc[5] & 0x60) >> 5); - //else da2->ma = da2->maback = da2->ma_latch + ((da2->crtc[5] & 0x60) >> 5); - //da2->ca = ((da2->crtc[0xe] << 8) | da2->crtc[0xf]) + ((da2->crtc[0xb] & 0x60) >> 5) + da2->ca_adj; -/* if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch; - else*/ da2->ma = da2->maback = da2->ma_latch; - da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj; - - da2->ma <<= 1; - da2->maback <<= 1; - da2->ca <<= 1; - - // da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); - } - if (da2->vc == da2->vtotal) - { - // da2_log("VC vtotal\n"); - - - // printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); - da2->vc = 0; - da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; - da2->dispon = 1; - da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; - da2->scrollcache = da2->attrc[LV_PANNING] & 7; - } - if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) - da2->con = 1; - } - // printf("2 %i\n",da2_vsyncstart); - //da2_log("da2_poll %i %i %i %i %i %i %i\n", ins, da2->dispofftime, da2->dispontime, da2->vidtime, cyc_total, da2->linepos, da2->vc); - //da2_log("r"); -} - -static void da2_loadfont(char* fname, void* p) { - da2_t* da2 = (da2_t*)p; - uint8_t buf; - //uint32_t code = 0; - 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 > DA2_FONTROM_SIZE) { - fsize = DA2_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) { - fread(&buf, sizeof(uint8_t), 1, mfile); - da2->mmio.font[j] = buf; - j++; - } - fclose(mfile); - return; -} - -/* 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} -}; - -void da2_reset_ioctl(da2_t* da2) -{ - da2->ioctl[LS_RESET] = 0x00; /* Bit 0: Reset sequencer */ - da2_outw(LS_INDEX, 0x0302, da2); /* Index 02, Bit 1: VGA passthrough, Bit 0: Character Mode */ - da2_outw(LS_INDEX, 0x0008, da2); /* Index 08, Bit 0: Enable MMIO */ -} - -static void -da2_reset(void* priv) -{ - da2_t* da2 = (da2_t*)priv; - - /* Initialize drawing */ - da2->bitblt.exec = DA2_BLT_CIDLE; - da2->render = da2_render_blank; - da2_reset_ioctl(da2); - - da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ - da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ - da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ - da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA-II, 1024 KB */ - da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8 ) << 1); /* Configuration 1 : Monitor ID 3 */ - da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ - da2->fctl[0] = 0x2b; /* 3E3h:0 */ - da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ - da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ - da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ - da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ - da2->ma_latch = 0; - da2->interlace = 0; - da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ - da2->attr_palette_enable = 0; /* disable attribute generator */ - - /* Set default color palette (Windows 3.1 display driver won't reset palette) */ - da2_out(0x3c8, 0, da2); - for (int i = 0; i < 256; i++) { - da2_out(0x3c9, ps55_palette_color[i & 0x3F][0], da2); - da2_out(0x3c9, ps55_palette_color[i & 0x3F][1], da2); - da2_out(0x3c9, ps55_palette_color[i & 0x3F][2], da2); - } -} - -static void *da2_init() -{ - //Todo: init regs, gaiji memory, video memory, I/O handlers, font ROM - - if (svga_get_pri() == NULL) - return NULL; - svga_t *mb_vga = svga_get_pri(); - mb_vga->cable_connected = 0; - - da2_t* da2 = malloc(sizeof(da2_t)); - da2->mb_vga = mb_vga; - - da2->dispontime = 1000ull << 32; - da2->dispofftime = 1000ull << 32; - int memsize = 1024 * 1024; - da2->vram = malloc(memsize); - da2->vram_mask = memsize - 1; - da2->cram = malloc(0x1000); - da2->vram_display_mask = DA2_MASK_CRAM; - da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h - da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ - - da2->mmio.charset = device_get_config_int("charset"); - da2->mmio.font= malloc(DA2_FONTROM_SIZE); - switch(da2->mmio.charset) - { - case DA2_DCONFIG_CHARSET_HANT: - da2_loadfont(DA2_FONTROM_PATH_HANT, da2); - break; - case DA2_DCONFIG_CHARSET_JPAN: - da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); - break; - } - - mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); - da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); - memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ -#ifdef ENABLE_DA2_DEBUGBLT - da2->bitblt.debug_reg = malloc(DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE); - da2->mmdbg_fp = fopen("da2_mmiowdat.txt", "w"); - da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); - da2->bitblt.debug_reg_ip = 0; -#endif - da2->bitblt.payload_addr = 0; - da2_reset(da2); - - mem_mapping_add(&da2->mmio.mapping, 0xA0000, 0x20000, da2_mmio_read, da2_mmio_readw, NULL, da2_mmio_write, da2_mmio_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); - //da2_log("DA2mmio new mapping: %X, base: %x, size: %x\n", &da2->mmio.mapping, da2->mmio.mapping.base, da2->mmio.mapping.size); - - mem_mapping_disable(&da2->mmio.mapping); - - mem_mapping_add(&da2->cmapping, 0xE0000, 0x1000, da2_code_readb, da2_code_readw, NULL, da2_code_writeb, da2_code_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); - - mem_mapping_disable(&da2->cmapping); - - timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ - timer_add(&da2->bitblt.timer, da2_bitblt_exec, da2, 0); - - return da2; -} -static int da2_available() -{ - return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); -} - -void da2_close(void *p) -{ - da2_t *da2 = (da2_t *)p; - - /* dump mem for debug */ -#ifndef RELEASE_BUILD - FILE* f; - f = fopen("da2_cram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->cram, 0x1000, 1, f); - fclose(f); - } - f = fopen("da2_vram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->vram, 1024*1024, 1, f); - fclose(f); - } - f = fopen("da2_gram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->mmio.ram, 256*1024, 1, f); - fclose(f); - } - f = fopen("da2_attrpal.dmp", "wb"); - if (f != NULL) { - fwrite(da2->attrc, 32, 1, f); - fclose(f); - } - f = fopen("da2_dacrgb.dmp", "wb"); - if (f != NULL) { - fwrite(da2->vgapal, 3*256, 1, f); - fclose(f); - } - f = fopen("da2_daregs.txt", "w"); - if (f != NULL) { - for (int i=0;i<0x10;i++) - fprintf(f, "3e1(ioctl) %02X: %4X\n", i, da2->ioctl[i]); - for (int i = 0; i < 0x20; i++) - fprintf(f, "3e3(fctl) %02X: %4X\n", i, da2->fctl[i]); - for (int i = 0; i < 0x20; i++) - fprintf(f, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); - for (int i = 0; i < 0x40; i++) - fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrc[i]); - for (int i = 0; i < 0x10; i++) - fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); - for (int i = 0; i < 0x10; i++) - fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); - fclose(f); - } -#endif -#ifdef ENABLE_DA2_DEBUGBLT - f = fopen("da2_bltdump.csv", "w"); - if (f != NULL && da2->bitblt.debug_reg_ip > 0) { - /* print header */ - for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { - if (da2->bitblt.debug_reg[(da2->bitblt.debug_reg_ip - 1) * DA2_DEBUG_BLTLOG_SIZE + y] != DA2_DEBUG_BLT_NEVERUSED) - fprintf(f, "\"%02X\"\t", y); - } - fprintf(f, "\n"); - /* print data */ - for (int x = 0; x < da2->bitblt.debug_reg_ip; x++) { - for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { - if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_NEVERUSED) - ; - else if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_USEDRESET) - fprintf(f, "\"\"\t"); - else - fprintf(f, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]); - } - fprintf(f, "\n"); - } - fclose(f); - } - if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); - if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); - free(da2->bitblt.debug_reg); -#endif - free(da2->cram); - free(da2->vram); - free(da2->changedvram); - free(da2->mmio.font); - free(da2); -} - -void da2_speed_changed(void *p) -{ - da2_t* da2 = (da2_t*)p; - da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); - da2_recalctimings(da2); -} - -void da2_force_redraw(void *p) -{ - da2_t* da2 = (da2_t*)p; - - da2->fullchange = changeframecount; -} - -static const device_config_t da2_configuration[] = { - // clang-format off - { - .name = "charset", - .description = "Charset", - .type = CONFIG_SELECTION, - .default_int = DA2_DCONFIG_CHARSET_JPAN, - .selection = { - { - .description = "932 (Japanese)", - .value = DA2_DCONFIG_CHARSET_JPAN - }, - { - .description = "938 (Traditional Chinese)", - .value = DA2_DCONFIG_CHARSET_HANT - }, - { .description = "" } - } - }, - { - .name = "montype", - .description = "Monitor type", - .type = CONFIG_SELECTION, - .default_int = DA2_DCONFIG_MONTYPE_COLOR, - .selection = { - { - .description = "Color", - .value = DA2_DCONFIG_MONTYPE_COLOR - }, - { - .description = "IBM 8515", - .value = DA2_DCONFIG_MONTYPE_8515 - }, - { - .description = "Grayscale", - .value = DA2_DCONFIG_MONTYPE_MONO - }, - { .description = "" } - } - }, - { .name = "", .description = "", .type = CONFIG_END } - // clang-format on -}; - -const device_t ps55da2_device = { - .name = "IBM Display Adapter II (MCA)", - .internal_name = "ps55da2", - .flags = DEVICE_MCA, - .local = 0, - .init = da2_init, - .close = da2_close, - .reset = da2_reset, - { .available = da2_available }, - .speed_changed = da2_speed_changed, - .force_redraw = da2_force_redraw, - .config = da2_configuration -}; - -void -da2_device_add(void) -{ - if (!da2_standalone_enabled) - return; - - if (machine_has_bus(machine, MACHINE_BUS_MCA)) - device_add(&ps55da2_device); - else - return; -} +/* + * 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. + * + * IBM PS/55 Display Adapter II emulation. + * + * Authors: Akamaki. + * + * Copyright 2024 Akamaki. + */ + +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/machine.h> +#include <86box/mem.h> +#include <86box/timer.h> +#include <86box/mca.h> +#include <86box/rom.h> +#include <86box/plat.h> +#include <86box/thread.h> +#include <86box/video.h> +#include <86box/vid_ps55da2.h> +#include <86box/vid_svga.h> +#include <86box/vid_svga_render.h> +#include "cpu.h" + +#define DA2_FONTROM_PATH_JPAN "roms/video/da2/94X1320.BIN" +#define DA2_FONTROM_PATH_HANT "roms/video/da2/23F2698.BIN" +#define DA2_FONTROM_SIZE 1536*1024 +#define DA2_FONTROM_BASESBCS 0x98000 +#define DA2_GAIJIRAM_SBCS 0x34000 +#define DA2_GAIJIRAM_SBEX 0x3c000 +#define DA2_INVALIDACCESS8 0xff +#define DA2_MASK_MMIO 0x1ffff +#define DA2_MASK_GRAM 0x1ffff +#define DA2_MASK_CRAM 0xfff +#define DA2_MASK_GAIJIRAM 0x3ffff +#define DA2_PIXELCLOCK 58000000.0 +#define DA2_BLT_MEMSIZE 0x100 +#define DA2_BLT_REGSIZE 0x40 +#define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) +#define DA2_DEBUG_BLTLOG_MAX 256*1024 +#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe +#define DA2_DEBUG_BLT_USEDRESET 0xfefefe +#define DA2_DCONFIG_CHARSET_JPAN 0 /* for Code page 932 Japanese */ +//#define DA2_DCONFIG_CHARSET_HANG 1 /* for Code page 934 Hangul */ +//#define DA2_DCONFIG_CHARSET_HANS 2 /* for Code page 936 Simplified Chinese */ +#define DA2_DCONFIG_CHARSET_HANT 3 /* for Code page 938 Traditional Chinese */ +#define DA2_DCONFIG_MONTYPE_COLOR 0x0A +#define DA2_DCONFIG_MONTYPE_8515 0x0B +#define DA2_DCONFIG_MONTYPE_MONO 0x09 + +#define DA2_BLT_CIDLE 0 +#define DA2_BLT_CFILLRECT 1 +#define DA2_BLT_CFILLTILE 2 +#define DA2_BLT_CCOPYF 3 +#define DA2_BLT_CCOPYR 4 +#define DA2_BLT_CPUTCHAR 5 +#define DA2_BLT_CDONE 6 +#define DA2_BLT_CLOAD 7 +/* POS ID = 0xeffe : Display Adapter II, III, V */ +#define DA2_POSID_H 0xef +#define DA2_POSID_L 0xfe +/* + [Identification] + POS ID SYS ID + EFFFh * Display Adapter (PS/55 Model 5571-S0A) [Toledo] + E013h * Layout Display Terminal (PS/55-5571 RPQ model) [LDT] + EFFEh * Display Adapter II (I/O 3E0:0A = xx0x xxxx) [Atlas] + |- FFF2h Display Adapter B2 (I/O 3E0:0A = xx1x xxxx) (PS/55 Model 5530Z-SX) + |- FDFEh Display Adapter B2 (I/O 3E0:0A = xx1x xxxx) (PS/55 Model 5550-V2) + |- * Display Adapter III,V (I/O 3E0:0A = xx1x xxxx) + ECECh FF4Fh Display Adapter B1 (PS/55 Model 5531Z-SX) [Atlas-KENT] + |- * Display Adapter IV + ECCEh * Display Adapter IV + 901Fh * Display Adapter A2 + 901Dh * Display Adapter A1 [Atlas II] + 901Eh * Plasma Display Adapter + EFD8h * Display Adapter/J [Atlas-SP2] + + [Japanese DOS and Display Adapter compatibility] + | POS ID | Adapter Name | K3.31 | J4.04 | J5.02 | OS2 J1.3 | Win3 | + |------------|-----------------------------|:-----:|:-----:|:-----:|:--------:|:----:| + | EFFFh | Display Adapter | X | | | ? | | + | FFEDh | ? [Atlas EVT] | X | | | ? | | + | FFFDh | ? [LDT EVT] | X | | | ? | | + | EFFEh | Display Adapter II,III,V,B2 | X | X | X | X | X | + | E013h | ? [LDT] | X | X | X | X | | + | ECCEh | Display Adapter IV | | X | X | X | | + | ECECh | Display Adapter IV,B1 | | X | X | X | X | + | 9000-901Fh | Display Adapter A1,A2 | | X | X | | X | + | EFD8h | Display Adapter /J | | | X | X | X | +*/ +/* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ +#define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ +//#define Mon_ID3 0x10 +#define FontCard 0x08 /* ? */ +/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ +#define Page_One 0x06 /* 80000h 110b */ +#define Page_Two 0x05 /* 100000h 101b */ +#define Page_Four 0x03 /* 200000h 011b */ + +/* IO 3E0/3E1:0Bh Hardware Configuration Value H (imported from OS/2 DDK) */ +#define AddPage 0x08 /* ? */ +//#define Mon_ID2 0x04 +//#define Mon_ID1 0x02 +//#define Mon_ID0 0x01 +/* Monitor ID (imported from OS/2 DDK 1.2) */ +//#define StarbuckC 0x0A //1 010b IBM 8514, 9518 color 1040x768 +//#define StarbuckM 0x09 //1 001b IBM 8507, 8604 grayscale +//#define Lark_B 0x02 //0 010b IBM 9517 color 1040x768 but 4bpp +//#define Dallas 0x0B //1 011b IBM 8515, 9515 color 1040x740 palette B + +/* DA2 Registers (imported from OS/2 DDK) */ +#define AC_REG 0x3EE +#define AC_DMAE 0x80 +#define AC_FONT_SEL 0x40 +#define FONT_BANK 0x3EF +#define LS_INDEX 0x3E0 +#define LS_DATA 0x3E1 +#define LS_RESET 0x00 +#define LS_MODE 0x02 +#define LS_STATUS 0x03 /* added */ +#define LS_MMIO 0x08 /* added */ +#define LS_CONFIG1 0x0a +#define LS_CONFIG2 0x0b /* added */ +#define LF_INDEX 0x3e2 +#define LF_DATA 0x3e3 +#define LF_MMIO_SEL 0x08 /* added */ +#define LF_MMIO_ADDR 0x0A /* added */ +#define LF_MMIO_MODE 0x0B /* added */ +#define LC_INDEX 0x3E4 +#define LC_DATA 0x3E5 +#define LC_HORIZONTAL_TOTAL 0x00 +#define LC_H_DISPLAY_ENABLE_END 0x01 +#define LC_START_H_BLANKING 0x02 +#define LC_END_H_BLANKING 0x03 +#define LC_START_HSYNC_PULSE 0x04 +#define LC_END_HSYNC_PULSE 0x05 +#define LC_VERTICAL_TOTALJ 0x06 +#define LC_CRTC_OVERFLOW 0x07 +#define LC_PRESET_ROW_SCANJ 0x08 +#define LC_MAXIMUM_SCAN_LINE 0x09 +#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_ROW_CURSOR_LOC 0x0E +#define LC_CURSOR_LOC_LOWJ 0x0F +#define LC_COLUMN_CURSOR_LOC 0x0F +#define LC_VERTICAL_SYNC_START 0x10 +#define LC_LIGHT_PEN_HIGH 0x10 +#define LC_VERTICAL_SYNC_END 0x11 +#define LC_LIGHT_PEN_LOW 0x11 +#define LC_V_DISPLAY_ENABLE_END 0x12 +#define LC_OFFSET 0x13 +#define LC_UNDERLINE_LOCATION 0x14 +#define LC_START_VERTICAL_BLANK 0x15 +#define LC_END_VERTICAL_BLANK 0x16 +#define LC_LC_MODE_CONTROL 0x17 +#define LC_LINE_COMPAREJ 0x18 +#define LC_START_H_DISPLAY_ENAB 0x19 +#define LC_START_V_DISPLAY_ENAB 0x1A +#define LC_VIEWPORT_COMMAND 0x1B +#define LC_VIEWPORT_SELECT 0x1C +#define LC_VIEWPORT_PRIORITY 0x1D +#define LC_COMMAND 0x1E +#define LC_COMPATIBILITY 0x1F +#define LC_VIEWPORT_NUMBER 0x1F +#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 LG_INDEX 0x3EA +#define LG_DATA 0x3EB +#define LG_SET_RESETJ 0x00 +#define LG_ENABLE_SRJ 0x01 +#define LG_COLOR_COMPAREJ 0x02 +#define LG_DATA_ROTATION 0x03 +#define LG_READ_MAP_SELECT 0x04 +#define LG_MODE 0x05 +#define LG_COMPLEMENT 0x06 +#define LG_COLOR_DONT_CARE 0x07 +#define LG_BIT_MASK_LOW 0x08 +#define LG_BIT_MASK_HIGH 0x09 +#define LG_MAP_MASKJ 0x0A +#define LG_COMMAND 0x0B +#define LG_SET_RESET_2 0x10 + +#ifndef RELEASE_BUILD +#define ENABLE_DA2_LOG 1 +#endif + +#ifdef ENABLE_DA2_LOG +int da2_do_log = ENABLE_DA2_LOG; + +static void +da2_log(const char* fmt, ...) +{ + va_list ap; + + if (da2_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define da2_log(fmt, ...) +#endif +#ifndef RELEASE_BUILD +# define ENABLE_DA2_DEBUGBLT 1 +#endif + +typedef struct da2_t +{ + //mem_mapping_t vmapping; + mem_mapping_t cmapping; + + //uint8_t crtcreg; + uint8_t ioctl[16]; + uint8_t fctl[32]; + uint16_t crtc[128]; + uint8_t gdcreg[64]; + uint8_t reg3ee[16]; + int gdcaddr; + uint8_t attrc[0x40]; + int attraddr, attrff; + int attr_palette_enable; + //uint8_t seqregs[64]; + int outflipflop; + int inflipflop; + int iolatch; + + int ioctladdr; + int fctladdr; + int crtcaddr; + + uint32_t decode_mask; + uint32_t vram_max; + uint32_t vram_mask; + + uint32_t gdcla[8]; + uint32_t gdcinput[8]; + uint32_t gdcsrc[8]; + uint32_t debug_vramold[8]; + + uint8_t dac_mask, dac_status; + int dac_read, dac_write, dac_pos; + int dac_r, dac_g; + + uint8_t cgastat; + + uint8_t plane_mask; + + int fb_only; + + int fast; + uint8_t colourcompare, colournocare; + int readmode, writemode, readplane; + uint8_t writemask; + uint32_t charseta, charsetb; + + uint8_t egapal[16]; + uint32_t pallook[512]; + PALETTE vgapal; + + int vtotal, dispend, vsyncstart, split, vblankstart; + int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; + int lowres, interlace; + int rowcount; + double clock; + uint32_t ma_latch, ca_adj; + + uint64_t dispontime, dispofftime; + pc_timer_t timer; + uint64_t da2const; + + int dispon; + int hdisp_on; + + uint32_t ma, maback, ca; + int vc; + int sc; + int linepos, vslines, linecountff, oddeven; + int con, cursoron, blink, blinkconf; + int scrollcache; + int char_width; + + int firstline, lastline; + int firstline_draw, lastline_draw; + int displine; + + /* Attribute Buffer E0000-E0FFFh (4 KB) */ + uint8_t *cram; + /* (cram size - 1) >> 3 = 0xFFF */ + //uint32_t cram_display_mask; + /* APA Buffer A0000-BFFFFh (128 KB) */ + uint8_t *vram; + /* addr >> 12 = xx000h */ + uint8_t *changedvram; + /* (vram size - 1) >> 3 = 0x1FFFF */ + uint32_t vram_display_mask; + + //uint32_t write_bank, read_bank; + + int fullchange; + + void (*render)(struct da2_t* da2); + + /*If set then another device is driving the monitor output and the SVGA + card should not attempt to display anything */ + int override; + + /* end VGA compatible regs*/ + struct + { + int enable; + mem_mapping_t mapping; + uint8_t ram[256 * 1024]; + uint8_t *font; + int charset; + } mmio; + + struct { + int bitshift_destr; + int raster_op; + uint8_t payload[DA2_BLT_MEMSIZE]; + int32_t reg[DA2_BLT_REGSIZE];//must be signed int + int32_t* debug_reg;//for debug + int debug_reg_ip;//for debug + int payload_addr; + pc_timer_t timer; + int64_t timerspeed; + int exec; + int indata; + int32_t destaddr; + int32_t srcaddr; + int32_t size_x, tile_w; + int32_t size_y; + int16_t destpitch; + int16_t srcpitch; + int32_t fcolor; + int32_t maskl, maskr; + int x, y; + } bitblt; + + FILE* mmdbg_fp; + FILE* mmrdbg_fp; + uint32_t mmdbg_vidaddr; + uint32_t mmrdbg_vidaddr; + + uint8_t pos_regs[8]; + svga_t *mb_vga; + uint8_t monitorid; + + int old_pos2; +} da2_t; + +void da2_recalctimings(da2_t* da2); +static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p); +void da2_bitblt_exec(void* p); +void da2_updatevidselector(da2_t* da2); +void da2_reset_ioctl(da2_t* da2); +static void da2_reset(void* priv); + +typedef union { + uint32_t d; + uint8_t b[4]; +} DA2_VidSeq32; + +typedef struct { + uint32_t p8[8]; +} pixel32; + +/* safety read for internal functions */ +uint32_t DA2_readvram_s(uint32_t addr, da2_t* da2) +{ + if (addr & ~da2->vram_mask) return -1; + return da2->vram[addr]; +} + +void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32* srcpx, da2_t* da2) +{ + uint32_t writepx[8]; + destaddr &= 0xfffffffe;/* align to word address to work bit shift correctly */ + //da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); + da2->changedvram[(da2->vram_display_mask & destaddr) >> 12] = changeframecount; + da2->changedvram[(da2->vram_display_mask & (destaddr+1)) >> 12] = changeframecount; + destaddr <<= 3; + /* read destination data with big endian order */ + for (int i = 0; i < 8; i++) + writepx[i] = DA2_readvram_s((destaddr + 24) | i, da2) + | (DA2_readvram_s((destaddr + 16) | i, da2) << 8) + | (DA2_readvram_s((destaddr + 8) | i, da2) << 16) + | (DA2_readvram_s((destaddr + 0) | i, da2) << 24); + + DA2_VidSeq32 mask32in; mask32in.d = (uint32_t)mask; + DA2_VidSeq32 mask32; mask32.d = 0; + mask32.b[3] = mask32in.b[0]; + mask32.b[2] = mask32in.b[1]; + mask32.d &= 0xffff0000; + for (int i = 0; i < 8; i++) + { + if (da2->bitblt.bitshift_destr > 0) + srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; + switch (da2->bitblt.raster_op) { + case 0x00: /* None */ + writepx[i] &= ~mask32.d; + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x01: /* AND */ + writepx[i] &= srcpx->p8[i] | ~mask32.d; + break; + case 0x02: /* OR */ + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x03: /* XOR */ + writepx[i] ^= srcpx->p8[i] & mask32.d; + break; + } + } + for (int i = 0; i < 8; i++) { + da2->vram[(da2->vram_mask & destaddr) | i] = (writepx[i] >> 24) & 0xff; + da2->vram[(da2->vram_mask & (destaddr + 8)) | i] = (writepx[i] >> 16) & 0xff; + } +} + +void DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t* da2) +{ + pixel32 srcpx; + //fill data with input color + for (int i = 0; i < 8; i++) + srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0;//read in word + + DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +/* +Param Desc +01 Color +03 Bit Shift +04 Select plane? +05 Dir(10 or 11) + Command?(40 or 48) +08 Mask Left +09 Mask Right +0A Plane Mask? +0B ROP?(8h or 200h + 0-3h) +0D +20 Exec (1) +21 ? +22 ? +23 Tile W +28 Tile H +29 Dest Addr +2A Src Addr +2B Tile Addr +33 Size W +35 Size H + +*/ +void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) +{ + pixel32 srcpx; + srcaddr &= 0xfffffffe; + srcaddr <<= 3; + for (int i = 0; i < 8; i++) + srcpx.p8[i] = DA2_readvram_s((srcaddr + 24) | i, da2) + | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) + | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) + | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24);//read in word + + DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) +{ + pixel32 srcpx; + if (srcaddr >= DA2_FONTROM_SIZE) { + da2_log("DA2 Putchar Addr Error %x\n", srcaddr); + return; + } + for (int i = 0; i < 8; i++) + srcpx.p8[i] = ((uint32_t)da2->mmio.font[srcaddr] << 24) + | ((uint32_t)da2->mmio.font[srcaddr + 1] << 16) + | ((uint32_t)da2->mmio.font[srcaddr + 2] << 8) + | ((uint32_t)da2->mmio.font[srcaddr + 3] << 0);//read in word + + DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); +} +#ifdef ENABLE_DA2_DEBUGBLT +uint8_t pixel1tohex(uint32_t addr, int index, da2_t* da2) { + uint8_t pixeldata = 0; + for (int j = 0; j < 8; j++) { + if (da2->vram[(da2->vram_mask & (addr << 3)) | j] & (1 << (7 - index))) pixeldata++; + } + return pixeldata; +} +void print_pixelbyte(uint32_t addr, da2_t* da2) { + for (int i = 0; i < 8; i++) + { + pclog("%X", pixel1tohex(addr, i, da2)); + } +} +void print_bytetobin(uint8_t b) { + for (int i = 0; i < 8; i++) + { + if(b & 0x80) + pclog("1"); + else + pclog("0"); + b <<= 1; + } +} +//Convert internal char code to Shift JIS code +inline int isKanji1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); } +inline int isKanji2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); } +uint16_t IBMJtoSJIS(uint16_t knj) +{ + if (knj < 0x100) return 0xffff; + knj -= 0x100; + if (knj <= 0x1f7d) + ;/* do nothing */ + else if (knj >= 0xb700 && knj <= 0xb75f) { + knj -= 0x90ec; + } + else if (knj >= 0xb3f0 && knj <= 0xb67f) { + knj -= 0x906c; + } + else if (knj >= 0x8000 && knj <= 0x8183) + { + knj -= 0x5524; + } + else + return 0xffff; + uint32_t knj1 = knj / 0xBC; + uint32_t knj2 = knj - (knj1 * 0xBC); + knj1 += 0x81; + if (knj1 > 0x9F) knj1 += 0x40; + knj2 += 0x40; + if (knj2 > 0x7E) knj2++; + //if (!isKanji1(knj1)) return 0xffff; + //if (!isKanji2(knj2)) return 0xffff; + knj = knj1 << 8; + knj |= knj2; + return knj; +} +#endif +void da2_bitblt_load(da2_t* da2) +{ + uint32_t value32; + uint64_t value64; + da2_log("BITBLT loading params\n"); + //da2_log("BitBlt memory:\n"); + //if (da2->bitblt.payload[0] != 0) + // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) + // { + // int i = j * 8; + // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + // da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + // } + int i = 0; + while (i < DA2_BLT_MEMSIZE) + { + if (da2->bitblt.reg[0x20] & 0x1) + break; + switch (da2->bitblt.payload[i]) { + case 0x88: + case 0x89: + case 0x95: + value32 = da2->bitblt.payload[i + 3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 2]; + da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + i += 3; + break; + case 0x91: + value32 = da2->bitblt.payload[i + 5]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 4]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 2]; + da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + i += 5; + break; + case 0x99: + value64 = da2->bitblt.payload[i + 7]; + value64 <<= 8; + value64 = da2->bitblt.payload[i + 6]; + value64 <<= 8; + value64 = da2->bitblt.payload[i + 5]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 4]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 3]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 2]; + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; + da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + i += 7; + break; + case 0x00: + break; + default: + da2_log("da2_ParseBLT: Unknown PreOP!\n"); + break; + } + i++; + } + da2->bitblt.exec = DA2_BLT_CIDLE; + /* clear payload memory */ + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + da2->bitblt.payload_addr = 0; + /* [89] 20: 0001 (1) then execute payload */ + if (da2->bitblt.reg[0x20] & 0x1) + { +#ifdef ENABLE_DA2_DEBUGBLT + for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { + //if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); + } + for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { + da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; + } + da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * (da2->bitblt.debug_reg_ip + 1) - 1] = 0; + da2->bitblt.debug_reg_ip++; + if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; +#endif + da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f);//set bit shift + da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03;//01 AND, 03 XOR + da2_log("bitblt execute 05: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); + for (int i = 0; i <= 0xb; i++) + da2_log("%02x ", da2->gdcreg[i]); + da2_log("\n"); + + da2->bitblt.destaddr = da2->bitblt.reg[0x29]; + da2->bitblt.size_x = da2->bitblt.reg[0x33]; + da2->bitblt.size_y = da2->bitblt.reg[0x35]; + da2->bitblt.destpitch = da2->bitblt.reg[0x21]; + da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; + if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; + { + da2->bitblt.destaddr -= 2; + da2->bitblt.size_x += 1; + da2->bitblt.destpitch -= 2; + da2->bitblt.srcpitch -= 2; + } + da2->bitblt.fcolor = da2->bitblt.reg[0x0]; + da2->bitblt.maskl = da2->bitblt.reg[0x8]; + da2->bitblt.maskr = da2->bitblt.reg[0x9]; + da2->bitblt.x = 0; + da2->bitblt.y = 0; + da2->bitblt.exec = DA2_BLT_CDONE; + timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + + if (da2->bitblt.reg[0x2f] < 0x80)//MS Paint 3.1 will cause hang up in 256 color mode + { + da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); + da2->bitblt.exec = DA2_BLT_CDONE; + } + else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ + da2->bitblt.exec = DA2_BLT_CPUTCHAR; + /* Todo: addressing */ + //if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; + //{ + // da2->bitblt.destaddr += 2; + // da2->bitblt.size_x -= 1; + // da2->bitblt.destpitch += 2; + // da2->bitblt.srcpitch += 2; + //} + uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2; + da2->bitblt.destaddr += 2; + da2->bitblt.srcpitch = 0; + da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ + da2->bitblt.bitshift_destr += 1; + da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); + } + else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { + da2->bitblt.exec = DA2_BLT_CPUTCHAR; + uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; + da2->bitblt.destaddr += 2; + da2->bitblt.srcpitch = 0; + da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ + da2->bitblt.bitshift_destr += 1; + da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {/* Fill a rectangle(or draw a line) */ + da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); + da2->bitblt.exec = DA2_BLT_CFILLRECT; + da2->bitblt.destaddr += 2; + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */ + da2->bitblt.exec = DA2_BLT_CFILLTILE; + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle (transfer tile data multiple times) */ + da2->bitblt.exec = DA2_BLT_CFILLTILE; + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) {/* Block transfer (range copy) */ + da2->bitblt.exec = DA2_BLT_CCOPYF; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; + da2->bitblt.destaddr += 2; + da2_log("copy block src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + } + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) {/* Block copy but reversed direction */ + da2->bitblt.exec = DA2_BLT_CCOPYR; + da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + da2_log("copy blockR src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); + //da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); + } + } +} +void da2_bitblt_exec(void* p) +{ + da2_t* da2 = (da2_t*)p; + timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + //da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + switch (da2->bitblt.exec) + { + case DA2_BLT_CIDLE: + timer_disable(&da2->bitblt.timer); + break; + case DA2_BLT_CLOAD: + da2->bitblt.indata = 0; + da2_bitblt_load(da2); + break; + case DA2_BLT_CFILLRECT: + //da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + } + else if (da2->bitblt.x == 0) { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr += 2; + break; + case DA2_BLT_CFILLTILE: + int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + } + else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr += 2; + break; + case DA2_BLT_CCOPYF: + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + da2->bitblt.srcaddr += da2->bitblt.srcpitch + 2; + } + else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr += 2; + break; + case DA2_BLT_CCOPYR: + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr -= da2->bitblt.destpitch; + da2->bitblt.srcaddr -= da2->bitblt.srcpitch; + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + } + else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } + else { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + } + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + break; + case DA2_BLT_CPUTCHAR: + //da2->bitblt.y += 2; + da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; + pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); + //da2->bitblt.srcaddr += 2; + if(da2->bitblt.reg[0x12] < 0x100) + da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; + else + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; + print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); + print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); + pclog("\n"); + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + //if (1) { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 3) + { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += 130; + //da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + //da2->bitblt.srcaddr += -1; + } + else if (da2->bitblt.x == 0) { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + //da2->bitblt.x++; + } + else { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + //da2->bitblt.x++; + } + //da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2; + ////da2->bitblt.srcaddr += 2; + //da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; + break; + case DA2_BLT_CDONE: + /* initialize regs for debug dump */ + for (int i = 0; i < DA2_BLT_REGSIZE; i++) { + if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; + } + if(da2->bitblt.indata) da2->bitblt.exec = DA2_BLT_CLOAD; + else da2->bitblt.exec = DA2_BLT_CIDLE; + break; + } +} +void da2_bitblt_dopayload(da2_t* da2) { + if (da2->bitblt.exec == DA2_BLT_CIDLE) + { + da2->bitblt.exec = DA2_BLT_CLOAD; + //timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ + da2_log("da2 Do bitblt\n"); + while (da2->bitblt.exec != DA2_BLT_CIDLE) + { + da2_bitblt_exec(da2); + } + da2_log("da2 End bitblt %x\n", da2->bitblt.exec); + } +} + +void da2_out(uint16_t addr, uint16_t val, void *p) +{ + da2_t *da2 = (da2_t *)p; + int oldval; +/* +3E0 3E1 Sequencer Registers (undoc) +3E2 3E3 Font Registers (undoc) +3E4 3E5 CRT Control Registers (undoc) +3E8 3E9 Attribute Controller Registers (undoc) +3EA 3EB 3EC Graphics Contoller Registers +*/ + switch (addr) + { + case 0x3c6: /* PEL Mask */ + da2->dac_mask = val; + break; + case 0x3C7: /* Read Address */ + da2->dac_read = val; + da2->dac_pos = 0; + break; + case 0x3C8: /* Write Address */ + da2->dac_write = val; + da2->dac_read = val - 1; + da2->dac_pos = 0; + break; + case 0x3C9: /* Data */ + //da2_log("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI); + da2->dac_status = 0; + da2->fullchange = changeframecount; + switch (da2->dac_pos) + { + case 0: + da2->dac_r = val; + da2->dac_pos++; + break; + case 1: + da2->dac_g = val; + da2->dac_pos++; + break; + case 2: + da2->vgapal[da2->dac_write].r = da2->dac_r; + da2->vgapal[da2->dac_write].g = da2->dac_g; + da2->vgapal[da2->dac_write].b = val; + //if (da2->ramdac_type == RAMDAC_8BIT) + // da2->pallook[da2->dac_write] = makecol32(da2->vgapal[da2->dac_write].r, da2->vgapal[da2->dac_write].g, da2->vgapal[da2->dac_write].b); + //else + da2->pallook[da2->dac_write] = makecol32((da2->vgapal[da2->dac_write].r & 0x3f) * 4, (da2->vgapal[da2->dac_write].g & 0x3f) * 4, (da2->vgapal[da2->dac_write].b & 0x3f) * 4); + da2->dac_pos = 0; + da2->dac_write = (da2->dac_write + 1) & 255; + break; + } + break; + case LS_INDEX: + da2->ioctladdr = val; + break; + case LS_DATA: + //da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->ioctladdr, val, cs >> 4, cpu_state.pc); + if (da2->ioctladdr > 0xf) return; + if (da2->ioctl[da2->ioctladdr & 15] != val) + da2_log("ioctl changed %x: %x -> %x %04X:%04X\n", da2->ioctladdr & 15, da2->ioctl[da2->ioctladdr & 15], val, cs >> 4, cpu_state.pc); + oldval = da2->ioctl[da2->ioctladdr]; + da2->ioctl[da2->ioctladdr] = val; + if (oldval != val) { + if (da2->ioctladdr == LS_RESET && val & 0x01) /* Reset register */ + da2_reset_ioctl(da2); + else if (da2->ioctladdr == LS_MODE && ((oldval ^ val) & 0x03)) /* Mode register */ + { + da2->fullchange = changeframecount; + da2_recalctimings(da2); + da2_updatevidselector(da2); + } + else if (da2->ioctladdr == LS_MMIO && (!(val & 0x01))) /* MMIO register */ + { + //da2->bitblt.indata = 1; + } + } + break; + case LF_INDEX: + da2->fctladdr = val; + break; + case LF_DATA: + //da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); + if (da2->fctladdr > 0x1f) return; + if (da2->fctl[da2->fctladdr & 0x1f] != val) + da2_log("fctl changed %x: %x -> %x %04X:%04X\n", da2->fctladdr & 0x1f, da2->fctl[da2->fctladdr & 0x1f], val, cs >> 4, cpu_state.pc); + oldval = da2->fctl[da2->fctladdr]; + da2->fctl[da2->fctladdr] = val; + if (da2->fctladdr == 0 && oldval != val) + { + da2->fullchange = changeframecount; + da2_recalctimings(da2); + } + break; + case LC_INDEX: + da2->crtcaddr = val; + break; + case LC_DATA: + if (da2->crtcaddr > 0x1f) return; + //if (!(da2->crtcaddr == LC_CURSOR_LOC_HIGH || da2->crtcaddr == LC_CURSOR_LOC_LOWJ)) + // da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc); + if (!(da2->crtc[da2->crtcaddr] ^ val)) return; + switch (da2->crtcaddr) { + case LC_CRTC_OVERFLOW: + //return; + break; + case LC_MAXIMUM_SCAN_LINE: + if (!(da2->ioctl[LS_MODE] & 0x01)) val = 0; + break; + case LC_START_ADDRESS_HIGH: + //if (da2->crtc[0x1c] & 0x40) return; + break; + case LC_VERTICAL_TOTALJ: /* Vertical Total */ + case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ + case LC_V_DISPLAY_ENABLE_END: /* Vertical Display End Register */ + case LC_START_VERTICAL_BLANK: /* Start Vertical Blank Register */ + //val = 0x400; //for debugging bitblt + break; + case LC_VIEWPORT_SELECT: /* ViewPort Select? */ + //return; + break; + case LC_VIEWPORT_NUMBER: /* Compatibility? */ + break; + } + da2->crtc[da2->crtcaddr] = val; + switch (da2->crtcaddr) { + case LC_H_DISPLAY_ENABLE_END: + case LC_VERTICAL_TOTALJ: + case LC_MAXIMUM_SCAN_LINE: + case LC_START_ADDRESS_HIGH: + case LC_START_ADDRESS_LOW: + case LC_VERTICAL_SYNC_START: + case LC_V_DISPLAY_ENABLE_END: + case LC_START_VERTICAL_BLANK: + case LC_END_VERTICAL_BLANK: + case LC_VIEWPORT_PRIORITY: + da2->fullchange = changeframecount; + da2_recalctimings(da2); + break; + default: + break; + } + break; + case LV_PORT: + //da2_log("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc); + if (!da2->attrff) + { + // da2->attraddr = val & 31; + da2->attraddr = val & 0x3f; + if ((val & 0x20) != (da2->attr_palette_enable & 0x20)) + { + da2->fullchange = 3; + da2->attr_palette_enable = val & 0x20; + da2_recalctimings(da2); + } + //da2_log("set attraddr: %X\n", da2->attraddr); + } + else + { + if ((da2->attraddr == LV_PANNING) && (da2->attrc[LV_PANNING] != val)) + da2->fullchange = changeframecount; + if (da2->attrc[da2->attraddr & 0x3f] != val) + da2_log("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrc[da2->attraddr & 0x3f], val); + da2->attrc[da2->attraddr & 0x3f] = val; + //da2_log("set attrc %x: %x\n", da2->attraddr & 31, val); + if (da2->attraddr < 16) + da2->fullchange = changeframecount; + if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) + { + for (int c = 0; c < 16; c++) + { + //if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4); + //else da2->egapal[c] = (da2->attrc[c] & 0x3f) | ((da2->attrc[0x14] & 0xc) << 4); + if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = da2->attrc[c] & 0xf; + else da2->egapal[c] = da2->attrc[c] & 0x3f; + } + } + switch (da2->attraddr) + { + case LV_COLOR_PLANE_ENAB: + if ((val & 0xff) != da2->plane_mask) + da2->fullchange = changeframecount; + da2->plane_mask = val & 0xff; + break; + case LV_CURSOR_CONTROL: + switch (val & 0x18) { + case 0x08://fast blink + da2->blinkconf = 0x10; + break; + case 0x18://slow blink + da2->blinkconf = 0x20; + break; + default://no blink + da2->blinkconf = 0xff; + break; + } + break; + case LV_MODE_CONTROL: + case LV_ATTRIBUTE_CNTL: + case LV_COMPATIBILITY: + da2_recalctimings(da2); + break; + default: + break; + } + } + da2->attrff ^= 1; + break; + case 0x3E9: + /* VZ Editor's CURSOR.COM writes data via this port */ + da2->attrc[da2->attraddr & 0x3f] = val; + break; + case LG_INDEX: + da2->gdcaddr = val; + break; + case LG_DATA: + //if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); + //if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI); + switch (da2->gdcaddr & 0x1f) + { + case LG_READ_MAP_SELECT: + da2->readplane = val & 0x7; + break; + case LG_MODE: + da2->writemode = val & 3; + break; + case LG_MAP_MASKJ: + da2->writemask = val & 0xff; + break; + case LG_COMMAND: + break; + case LG_SET_RESET_2: + da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); + return; + } + da2->gdcreg[da2->gdcaddr & 15] = val & 0xff; + break; + //case 0x3ed: /* used by Windows 3.1 display driver */ + // da2->gdcreg[5] = val & 0xff; + // break; + default: + da2_log("DA2? Out addr %03X val %02X\n", addr, val); + break; + } +} + +uint16_t da2_in(uint16_t addr, void *p) +{ + da2_t * da2 = (da2_t *)p; + uint16_t temp; + + switch (addr) + { + case 0x3c3: + temp = 0; + break; + case 0x3c6: temp = da2->dac_mask; + break; + case 0x3c7: temp = da2->dac_status; + break; + case 0x3c8: temp = da2->dac_write; + break; + case 0x3c9: + da2->dac_status = 3; + switch (da2->dac_pos) + { + case 0: + da2->dac_pos++; + temp = da2->vgapal[da2->dac_read].r & 0x3f; + break; + case 1: + da2->dac_pos++; + temp = da2->vgapal[da2->dac_read].g & 0x3f; + break; + case 2: + da2->dac_pos = 0; + da2->dac_read = (da2->dac_read + 1) & 255; + temp = da2->vgapal[(da2->dac_read - 1) & 255].b & 0x3f; + break; + } + break; + case LS_INDEX: + temp = da2->ioctladdr; + break; + case LS_DATA: + //da2->ioctl[3] = 0x80;//3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) + if (da2->ioctladdr > 0xf) return DA2_INVALIDACCESS8; + temp = da2->ioctl[da2->ioctladdr]; + if (da2->ioctladdr == LS_STATUS) { /* Status register */ + if (da2->attrc[LV_COMPATIBILITY] & 0x08) { /* for detecting monitor type and cable wiring */ + if (da2->monitorid == DA2_DCONFIG_MONTYPE_MONO) { + /* grayscale monitor */ + if ((da2->vgapal[0].r >= 10) || (da2->vgapal[0].g >= 40) || (da2->vgapal[0].b >= 10)) + temp &= 0x7F; /* Inactive when the RGB output voltage is high (or the cable is not connected to a color monitor). */ + else + temp |= 0x80; /* Active when the RGB output voltage is low and the cable is connected to a color monitor. + If the cable or the monitor is wrong, it becomes inactive. */ + } else { + /* color monitor */ + if ((da2->vgapal[0].r + da2->vgapal[0].g + da2->vgapal[0].b) >= 80) + temp &= 0x7F; + else + temp |= 0x80; + } + } else { + temp |= 0x80; + } + temp &= 0xf6;//clear busy bits + if (da2->bitblt.indata) /* for OS/2 J1.3 */ + da2_bitblt_dopayload(da2); + if (da2->bitblt.exec != DA2_BLT_CIDLE) + { + //da2_log("exec:%x\n", da2->bitblt.exec); + temp |= 0x08;//wait(bit 3 + bit 0) + //if (!da2->bitblt.timer.enabled) + //{ + // da2_log("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); + // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + //} + } + if (da2->bitblt.indata) + temp |= 0x01; + //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + } + //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + break; + case LF_INDEX: + temp = da2->fctladdr; + break; + case LF_DATA: + if (da2->fctladdr > 0x1f) return DA2_INVALIDACCESS8; + temp = da2->fctl[da2->fctladdr]; + break; + case LC_INDEX: + temp = da2->crtcaddr; + break; + case LC_DATA: + if (da2->crtcaddr > 0x1f) return DA2_INVALIDACCESS8; + temp = da2->crtc[da2->crtcaddr]; + break; + case LV_PORT: + temp = da2->attraddr | da2->attr_palette_enable; + break; + case 0x3E9: + if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this may equiv to 3ba / 3da Input Status Register 1 */ + { + if (da2->cgastat & 0x01) + da2->cgastat &= ~0x30; + else + da2->cgastat ^= 0x30; + temp = da2->cgastat; + } + else + temp = da2->attrc[da2->attraddr]; + //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->attraddr, temp, cs >> 4, cpu_state.pc); + da2->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */ + break; + case LG_INDEX: + temp = da2->gdcaddr; + break; + case LG_DATA: + temp = da2->gdcreg[da2->gdcaddr & 0x1f]; + //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc); + break; + } + //da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + 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) +*/ +void da2_outb(uint16_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //da2_log("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); + da2->inflipflop = 0; + switch (addr) + { + case LS_DATA: + case LF_DATA: + case LC_DATA: + case LG_DATA: + if (da2->outflipflop) + { + /* out b(idx), out b(data), out b(data) */ + da2->iolatch |= (uint16_t)val << 8; + da2->outflipflop = 0; + } + else + {// + da2->iolatch = val; + da2->outflipflop = 1; + } + break; + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + default: + da2->iolatch = val; + da2->outflipflop = 0; + break; + } + da2_out(addr, da2->iolatch, da2); +} +void da2_outw(uint16_t addr, uint16_t val, void* p) +{ + //da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_t* da2 = (da2_t*)p; + da2->inflipflop = 0; + switch (addr) + { + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + da2_out(addr, val & 0xff, da2); + da2->iolatch = val >> 8; + da2_out(addr + 1, da2->iolatch, da2); + da2->outflipflop = 1; + break; + case LV_PORT: + da2->attrff = 0; + da2_out(addr, val & 0xff, da2); + da2_out(addr, val >> 8, da2); + da2->outflipflop = 0; + break; + case 0x3EC: + //da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_out(LG_DATA, val >> 8, da2); + break; + case 0x3ED: + da2->gdcaddr = LG_MODE; + da2_out(LG_DATA, val, da2); + break; + case LS_DATA: + case LF_DATA: + case LC_DATA: + case LG_DATA: + default: + da2_out(addr, val, da2); + da2->outflipflop = 0; + break; + case 0x3EE: + da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2->reg3ee[val & 0xff] = val >> 8; + break; + } +} +uint8_t da2_inb(uint16_t addr, void* p) +{ + uint8_t temp; + da2_t* da2 = (da2_t*)p; + da2->outflipflop = 0; + switch (addr) + { + case LC_DATA: + if (da2->inflipflop) + { + /* out b(idx), in b(low data), in b(high data) */ + temp = da2->iolatch >> 8; + da2->inflipflop = 0; + } + else + {// + da2->iolatch = da2_in(addr, da2); + temp = da2->iolatch & 0xff; + da2->inflipflop = 1; + } + break; + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + case LS_DATA: + case LF_DATA: + case LG_DATA: + default: + temp = da2_in(addr, da2) & 0xff; + da2->inflipflop = 0; + break; + } + //da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + return temp; +} +uint16_t da2_inw(uint16_t addr, void* p) +{ + //uint16_t temp; + da2_t* da2 = (da2_t*)p; + da2->inflipflop = 0; + da2->outflipflop = 0; + return da2_in(addr, da2); +} +/* IO 03DAh : Input Status Register 2 for DOSSHELL in DOS J4.0 */ +uint8_t da2_in_ISR(uint16_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + uint8_t temp = 0; + if (addr == 0x3da) { + if (da2->cgastat & 0x01) + da2->cgastat &= ~0x30; + else + da2->cgastat ^= 0x30; + temp = da2->cgastat; + } + //da2_log("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + return temp; +} + +void da2_out_ISR(uint16_t addr, uint8_t val, void* p) +{ + //da2_t* da2 = (da2_t*)p; + da2_log("DA2D Out %04X %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); +} + +/* +The IBM 5550 character mode addresses video memory between E0000h and E0FFFh. + [Character drawing] + SBCS: + 1 2 ... 13 + 1 | H.Grid + |---------------- + 2 | Space + 3 V| + .| + G| Font Pattern + r| (12x24 pixels) + i| + d| +26 |________________ +27 Space + ---------------- +28 Underscore ] + ---------------- >Cursor Position +29 ] + + DBCS: + 1 2 ... 13 1 2 ... 12 13 + 1 | H.Grid | H.Grid | + -|--------------------------|- + 2 | Space | Space | + -|--------------------------|- + 3 V| | |S + .| | |p + G| Font Pattern |a + r| (24x24 pixels) |c + i| | |e + d| | | +26 |_____________|____________| +27 | Space | Space + ------------------------------ +28 | Underscore | Underscore ] + ------------------------------ >Cursor Position +29 | | ] + + [Attributes] + Video mode 08h: + 7 6 5 4 3 2 1 0 + Blink |Under |HGrid |VGrid |Bright|Revers|FntSet|DBCS/SBCS| + + Video mode 0Eh: + -Blue |-Green|HGrid |VGrid |-Red |Revers|FntSet|DBCS/SBCS| + + Bit 1 switches the font bank to the Extended SBCS. DOS K3.x loads APL characters from $SYSEX24.FNT into it. + DOS Bunsho Program transfers 1/2 and 1/4 fonts fron the font ROM to the Extended SBCS. + This bit is not used for DBCS, but some apps set it as that column is right half of DBCS. + +[Font ROM Map (DA2, Japanese)] +The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh. + + Bank 0 + 4800- * + Bank 1, 2, 3 + * - * + Bank 4 + * -0DB6Fh ( 4800-8DB6Fh) : JIS X 0208 DBCS (24 x 24) (IBMJ code: 100-1F7Dh) + 10000-16D1Fh (90000-96D1Fh) : IBM Extended Characters (IBMJ code: 2ADC-2C5Fh) + 18000-1BFCFh (98000-9BFCFh) : JIS X 0201 SBCS (13 x 30) + 1C000-1FFFFh (9C000-9FFFFh) : Codepage 437 characters (13 x 30) + Bank 5 + 00000-0C68Fh (A0000-AC68Fh) : Gaiji used by DOS Bunsho + 10000-13FFFh (B0000-B3FFFh) : Extended SBCS (13 x 30) + 14000-1477Fh (B4000-B477Fh) : Half-width box drawing characters used by DOS Bunsho + 16000-17FFFh (B6000-B7FFFh) : Codepage 850 characters (13 x 30) + 18000-1A3FFh (B8000-BA3FFh) : CAD control icons and box drawing characters (32 x 32) + + Some models have the signature 80h, 01h placed at Bank 0:1AFFEh. (it disables hardware text drawing in OS/2 J1.3) + +[Font ROM Map (DA3, Traditional Chinese)] + Bank 0 - 11 : Valid Font ROM data + Bank 12 : Alias of bank 11 (At least, DOS T5.0 uses this on purpose.) + Bank 13 : All addresses return 0xFF + +[Gaiji RAM Map (DA2)] + Bank 0 00000-1FFFFh placed between A0000h-BFFFFh + 00000-1F7FFh(A0000-BF7FFh): Gaiji Non-resident (Kuten 103-114 ku,IBM: 2674-2ADBh) 1008 chs 128 bytes + 1F800-1FFFFh(BF800-BFFFFh): Gaiji Resident (SJIS: F040-F04Fh, IBM: 2384-2393h) 16 chs + + Bank 1 20000-3FFFFh placed between A0000h-BFFFFh + 20000-33FFFh(A0000-B3FFFh): Gaiji Resident (SJIS: F050-F39Ch, IBM: 2394-2613h) 640 chs + 34000-37FFFh(B4000-B7FFFh): Basic SBCS(00-FFh, ATTR bit 1 = off) + 38000-3AFFFh(B8000-BAFFFh): Gaiji Resident (SJIS: F39D-F3FCh, IBM: 2614-2673h) 96 chs + 3C000-3FFFFh(BC000-BFFFFh): Extended SBCS(00-FFh, ATTR bit 1 = on) + +[IBMJ code to Gaiji address conv tbl from DOS K3.3] + A B C + 2ADC, 2C5F, +5524 --> 8000 + 2614, 2673, +90EC --> B700 + 2384, 2613, +906C --> B3F0 + 0682, 1F7D, +0000 + + 8000 - 8183h 184h(388 characters) IBM Extended Characters + B3F0 - B75Fh 370h(880 characters) User-defined Characters +*/ + +/* Get character line pattern from jfont rom or gaiji volatile memory */ +uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void* p) { + da2_t* da2 = (da2_t*)p; + uint32_t font = 0; + int32_t fline = line - 2;//Start line of drawing character (line >= 1 AND line < 24 + 1 ) + if (code >= 0x8000 && code <= 0x8183) code -= 0x6000;//shift for IBM extended characters (I don't know how the real card works.) + if (code < DA2_FONTROM_SIZE / 72 && fline >= 0 && fline < 24) { + font = da2->mmio.font[code * 72 + fline * 3]; //1111 1111 + font <<= 8; //1111 1111 0000 0000 + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; //1111 1111 2222 0000 + font >>= 1; //0111 1111 1222 2000 + font <<= 4; //0111 1111 1222 2000 0000 + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; //0111 1111 1222 2000 2222 + font <<= 8; //0111 1111 1222 2000 2222 0000 0000 + font |= da2->mmio.font[code * 72 + fline * 3 + 2]; //0111 1111 1222 2000 2222 3333 3333 + font <<= 4; //0111 1111 1222 2000 2222 3333 3333 0000 + //font >>= 1;//put blank at column 1 (and 26) + } + else if (code >= 0xb000 && code <= 0xb75f) + { + //convert code->address in gaiji memory + code -= 0xb000; + code *= 0x80; + //code += 0xf800; + font = da2->mmio.ram[code + line * 4]; + font <<= 8; + font |= da2->mmio.ram[code + line * 4 + 1]; + font <<= 8; + font |= da2->mmio.ram[code + line * 4 + 2]; + font <<= 8; + font |= da2->mmio.ram[code + line * 4 + 3]; + } + else if (code > DA2_FONTROM_SIZE) + font = 0xffffffff; + else + font = 0; + return font; +} + +/* Reverse the bit order of attribute code IRGB to BGRI(used in Mode 3 and Cursor Color) */ +uint8_t IRGBtoBGRI(uint8_t attr) +{ + attr = ((attr & 0x01) << 7) | ((attr & 0x02) << 5) | ((attr & 0x04) << 3) | ((attr & 0x08) << 1); + return attr >>= 4; +} +/* Get the foreground color from the attribute byte */ +uint8_t getPS55ForeColor(uint8_t attr, da2_t* da2) +{ + uint8_t foreground = ~attr & 0x08;// 0000 1000 + foreground <<= 2; //0010 0000 + foreground |= ~attr & 0xc0;// 1110 0000 + foreground >>= 4;//0000 1110 + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;//bright color palette + return foreground; +} + +void da2_render_blank(da2_t* da2) +{ + int x, xx; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + + for (x = 0; x < da2->hdisp; x++) + { + for (xx = 0; xx < 13; xx++) ((uint32_t*)buffer32->line[da2->displine])[(x * 13) + xx + 32] = 0; + } +} +/* Display Adapter Mode 8, E Drawing */ +static void da2_render_text(da2_t* da2) +{ + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + + if (da2->fullchange) + { + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + int x; + int drawcursor; + uint8_t chr, attr; + int fg, bg; + uint32_t chr_dbcs; + int chr_wide = 0; + //da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); + for (x = 0; x < da2->hdisp; x += 13) + { + chr = da2->cram[(da2->ma) & da2->vram_display_mask]; + attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; + //if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80)//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, da2); + 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 = ((da2->blink & 0x20) || (!(attr & 0x80))) ? fg : bg; + //if(chr!=0x20) da2_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, da2->egapal[fg], da2->pallook[da2->egapal[fg]]); + } + //Draw character + for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->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 = da2->cram[((da2->ma) + 2) & da2->vram_display_mask]; + chr_dbcs <<= 8; + chr_dbcs |= chr; + // Get the font pattern + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->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 = DA2_GAIJIRAM_SBEX; + else + fontbase = DA2_GAIJIRAM_SBCS; + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font + font <<= 8; + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font + //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + } + } + // right half of DBCS + else + { + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + chr_wide = 0; + } + //Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. + if (da2->sc == 27 && attr & 0x40 && ~da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) {//Underscore only in monochrome mode + for (uint32_t n = 0; n < 13; n++) + p[n] = da2->pallook[da2->egapal[fg]];//under line (white) + } + //Column 1 (Vertical Line) + if (attr & 0x10) { + p[0] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];//vertical line (white) + } + if (da2->sc == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) {//HGrid + for (uint32_t n = 0; n < 13; n++) + p[n] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];//horizontal line (white) + } + //Drawing text cursor + drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); + if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) + { + int cursorwidth = (da2->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); + int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2;//Choose color 2 if mode 8 + fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : ((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] == da2->pallook[da2->egapal[cursorcolor]] || da2->egapal[bg] == da2->egapal[cursorcolor]) + p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[fg]] : da2->pallook[da2->egapal[bg]]; + else + p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[cursorcolor]] : p[n]; + } + da2->ma += 2; + p += 13; + } + da2->ma &= da2->vram_display_mask; + //da2->writelines++; + } +} + +/* Display Adapter Mode 3 Drawing */ +static void da2_render_textm3(da2_t* da2) +{ + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + + if (da2->fullchange) + { + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + int x; + int drawcursor; + uint8_t chr, attr, extattr; + int fg, bg; + uint32_t chr_dbcs; + int chr_wide = 0; + //da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); + for (x = 0; x < da2->hdisp; x += 13) + { + chr = da2->vram[(0x18000 + (da2->ma)) & da2->vram_mask]; + attr = da2->vram[((0x18000 + (da2->ma)) + 1) & da2->vram_mask]; + extattr = da2->vram[((0x10000 + (da2->ma)) + 1) & da2->vram_mask]; + //if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (0x18000 + da2->ma << 1) & da2->vram_mask, chr, attr); + bg = attr >> 4; + //if (da2->blink) bg &= ~0x8; + //fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg; + fg = attr & 0xf; + fg = IRGBtoBGRI(fg); + bg = IRGBtoBGRI(bg); + //Draw character + for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank + // SBCS or DBCS left half + if (chr_wide == 0) { + if (extattr & 0x01) chr_wide = 1; + // 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 = da2->vram[(0x18000 + (da2->ma) + 2) & da2->vram_mask]; + chr_dbcs <<= 8; + chr_dbcs |= chr; + // Get the font pattern + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; + font <<= 1; + } + } + else { + // the char code is SBCS (ANK) + uint32_t fontbase; + fontbase = DA2_GAIJIRAM_SBCS; + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font + font <<= 8; + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font + //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + } + } + // right half of DBCS + else + { + uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); + // Draw 13 dots + for (uint32_t n = 0; n < 13; n++) { + p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; + font <<= 1; + } + chr_wide = 0; + } + //Drawing text cursor + drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); + if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) + { + //int cursorwidth = (da2->crtc[0x1f] & 0x20 ? 26 : 13); + //int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;//Choose color 2 if mode 8 + //fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; + //bg = 0; + //if (attr & 0x04) {//Color 0 if reverse + // bg = fg; + // fg = 0; + //} + for (uint32_t n = 0; n < 13; n++) + p[n] = da2->pallook[da2->egapal[fg]]; + } + da2->ma += 2; + p += 13; + } + da2->ma &= da2->vram_display_mask; + //da2->writelines++; + } +} + +void da2_render_color_4bpp(da2_t* da2) +{ + int changed_offset = da2->ma >> 12; + //da2_log("ma %x cf %x\n", da2->ma, changed_offset); + da2->plane_mask &= 0x0f;//safety + + if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) + { + int x; + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + //da2_log("d %X\n", da2->ma); + + for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 + { + uint8_t edat[8]; + uint8_t dat; + + //get 8 pixels from vram + da2->ma &= da2->vram_display_mask; + *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); + da2->ma += 1; + + dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)); + p[0] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)); + p[1] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)); + p[2] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)); + p[3] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)); + p[4] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)); + p[5] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)); + p[6] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)); + p[7] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + p += 8; + } + //da2->writelines++; + } +} + +void da2_render_color_8bpp(da2_t* da2) +{ + int changed_offset = da2->ma >> 12; + //da2_log("ma %x cf %x\n", da2->ma, changed_offset); + + if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) + { + int x; + int offset = (8 - da2->scrollcache) + 24; + uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + //da2_log("d %X\n", da2->ma); + + for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 + { + uint8_t edat[8]; + uint8_t dat; + + //get 8 pixels from vram + da2->ma &= da2->vram_display_mask; + *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); + *(uint32_t*)(&edat[4]) = *(uint32_t*)(&da2->vram[(da2->ma << 3) + 4]); + da2->ma += 1; + + dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)) | + ((edat[4] >> 3) & (1 << 4)) | ((edat[5] >> 2) & (1 << 5)) | ((edat[6] >> 1) & (1 << 6)) | ((edat[7] >> 0) & (1 << 7)); + p[0] = da2->pallook[dat]; + dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)) | + ((edat[4] >> 2) & (1 << 4)) | ((edat[5] >> 1) & (1 << 5)) | ((edat[6] >> 0) & (1 << 6)) | ((edat[7] << 1) & (1 << 7)); + p[1] = da2->pallook[dat]; + dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)) | + ((edat[4] >> 1) & (1 << 4)) | ((edat[5] >> 0) & (1 << 5)) | ((edat[6] << 1) & (1 << 6)) | ((edat[7] << 2) & (1 << 7)); + p[2] = da2->pallook[dat]; + dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)) | + ((edat[4] >> 0) & (1 << 4)) | ((edat[5] << 1) & (1 << 5)) | ((edat[6] << 2) & (1 << 6)) | ((edat[7] << 3) & (1 << 7)); + p[3] = da2->pallook[dat]; + dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)) | + ((edat[4] << 1) & (1 << 4)) | ((edat[5] << 2) & (1 << 5)) | ((edat[6] << 3) & (1 << 6)) | ((edat[7] << 4) & (1 << 7)); + p[4] = da2->pallook[dat]; + dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)) | + ((edat[4] << 2) & (1 << 4)) | ((edat[5] << 3) & (1 << 5)) | ((edat[6] << 4) & (1 << 6)) | ((edat[7] << 5) & (1 << 7)); + p[5] = da2->pallook[dat]; + dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)) | + ((edat[4] << 3) & (1 << 4)) | ((edat[5] << 4) & (1 << 5)) | ((edat[6] << 5) & (1 << 6)) | ((edat[7] << 6) & (1 << 7)); + p[6] = da2->pallook[dat]; + dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)) | + ((edat[4] << 4) & (1 << 4)) | ((edat[5] << 5) & (1 << 5)) | ((edat[6] << 6) & (1 << 6)) | ((edat[7] << 7) & (1 << 7)); + p[7] = da2->pallook[dat]; + p += 8; + } + //da2->writelines++; + } +} + +void da2_updatevidselector(da2_t* da2) { + /* if VGA passthrough mode */ + da2_log("DA2 selector: %d\n", da2->ioctl[LS_MODE]); + if (da2->ioctl[LS_MODE] & 0x02) + { + da2->override = 1; + svga_set_override(da2->mb_vga, 0); + } + else + { + svga_set_override(da2->mb_vga, 1); + da2->override = 0; + } +} + +void da2_recalctimings(da2_t* da2) +{ + double crtcconst; + double _dispontime, _dispofftime, disptime; + + da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff;//w + da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff;//w + da2->vsyncstart = da2->crtc[LC_VERTICAL_SYNC_START] & 0xfff;//w + da2->split = da2->crtc[LC_LINE_COMPAREJ] & 0xfff;//w Line Compare + da2->split = 0xfff; + da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff;//w + da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; + + if (da2->crtc[LC_START_H_DISPLAY_ENAB] & 1) { + da2->hdisp--; + da2->dispend -= 29; + } + else { + //da2->vtotal += 2; + da2->dispend--; + //da2->vsyncstart++; + //da2->split++; + //da2->vblankstart++; + //da2->hdisp--; + } + + da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; + da2->htotal += 1; + + da2->rowoffset = da2->crtc[LC_OFFSET];//number of bytes in a scanline + + da2->clock = da2->da2const; + + //da2->lowres = da2->attrc[LV_MODE_CONTROL] & 0x40; + + //da2->interlace = 0; + + //da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b + da2->ca_adj = 0; + + da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE]; + + da2->hdisp_time = da2->hdisp; + da2->render = da2_render_blank; + //determine display mode + //if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) + if (da2->attrc[LV_COMPATIBILITY] & 0x08) + { + if (!(da2->ioctl[LS_MODE] & 0x01)) {//16 color graphics mode + da2->hdisp *= 16; + da2->char_width = 13; + da2->hdisp_old = da2->hdisp; + if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) { + da2_log("Set videomode to PS/55 8 bpp graphics.\n"); + da2->render = da2_render_color_8bpp; + da2->vram_display_mask = DA2_MASK_GRAM; + } + else {//PS/55 8-color + da2_log("Set videomode to PS/55 4 bpp graphics.\n"); + da2->vram_display_mask = DA2_MASK_GRAM; + da2->render = da2_render_color_4bpp; + } + } + else {//text mode + if (da2->attrc[LV_ATTRIBUTE_CNTL] & 1) { + da2_log("Set videomode to PS/55 Mode 03 text.\n"); + da2->render = da2_render_textm3; + da2->vram_display_mask = DA2_MASK_CRAM; + } + else {//PS/55 text(color/mono) + da2_log("Set videomode to PS/55 Mode 8/E text.\n"); + da2->render = da2_render_text; + da2->vram_display_mask = DA2_MASK_CRAM; + } + da2->hdisp *= 13; + da2->hdisp_old = da2->hdisp; + da2->char_width = 13; + } + } + else + { + da2_log("Set videomode to blank.\n"); + } + //if (!da2->scrblank && da2->attr_palette_enable) + //{ + //da2->render = da2_draw_text; + //} + + // da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); + + //if (da2->recalctimings_ex) + // da2->recalctimings_ex(da2); + + if (da2->vblankstart < da2->dispend) + da2->dispend = da2->vblankstart; + + crtcconst = da2->clock * da2->char_width; + + disptime = da2->htotal; + _dispontime = da2->hdisp_time; + + da2_log("Disptime %f dispontime %f hdisp %i\n", disptime, _dispontime, da2->hdisp); + //if (da2->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; } + _dispofftime = disptime - _dispontime; + _dispontime *= crtcconst; + _dispofftime *= crtcconst; + + da2->dispontime = (uint64_t)_dispontime; + da2->dispofftime = (uint64_t)_dispofftime; + if (da2->dispontime < TIMER_USEC) + da2->dispontime = TIMER_USEC; + if (da2->dispofftime < TIMER_USEC) + da2->dispofftime = TIMER_USEC; + da2_log("da2 horiz total %i display end %i vidclock %f\n",da2->crtc[0],da2->crtc[1],da2->clock); + // da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart); + // da2_log("total %f on %i cycles off %i cycles frame %i sec %i\n",disptime*crtcconst,da2->dispontime,da2->dispofftime,(da2->dispontime+da2->dispofftime)*da2->vtotal,(da2->dispontime+da2->dispofftime)*da2->vtotal*70); + + // da2_log("da2->render %08X\n", da2->render); +} + +uint8_t da2_mca_read(int port, void *p) +{ + da2_t *da2 = (da2_t *)p; + return da2->pos_regs[port & 7]; +} + +static void da2_mapping_update(da2_t *da2) +{ + if (!((da2->pos_regs[2] ^ da2->old_pos2) & 1)) return; + da2->old_pos2 = da2->pos_regs[2]; + //da2_recalc_mapping(da2); + if (da2->pos_regs[2] & 0x01) + { + da2_log("DA2 enable registers\n"); + for (int i = 0; i < 8; i++) + da2_log("DA2 POS[%d]: %x\n", i, da2->pos_regs[i]); + io_sethandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_sethandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_sethandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); + mem_mapping_enable(&da2->cmapping); + mem_mapping_enable(&da2->mmio.mapping); + timer_enable(&da2->timer); + } + else + { + da2_log("DA2 disable registers\n"); + timer_disable(&da2->timer); + mem_mapping_disable(&da2->cmapping); + mem_mapping_disable(&da2->mmio.mapping); + io_removehandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_removehandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_removehandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); + } +} + +void da2_mca_write(int port, uint8_t val, void *p) +{ + da2_t *da2 = (da2_t *)p; + + da2_log("da2_mca_write: port=%04x val=%02x\n", port, val); + + if (port < 0x102) + return; + da2->pos_regs[port & 7] = val; + + da2_mapping_update(da2); +} + +static uint8_t da2_mca_feedb(void* priv) +{ + const da2_t* da2 = (da2_t*)priv; + + return da2->pos_regs[2] & 0x01; +} + +static void da2_mca_reset(void *p) +{ + da2_t *da2 = (da2_t *)p; + da2_reset(da2); + da2_mca_write(0x102, 0, da2); +} +// +static void da2_gdcropB(uint32_t addr, da2_t* da2) { + for (int i = 0; i < 8; i++) { + if (da2->writemask & (1 << i)) { + //da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW]); + switch (da2->gdcreg[LG_COMMAND] & 0x03) + { + case 0: /*Set*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 1: /*AND*/ + //da2->vram[addr | i] = (da2->gdcinput[i] | ~da2->gdcreg[LG_BIT_MASK_LOW]) & da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 2: /*OR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 3: /*XOR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) ^ da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + } + } + } +} +static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t* da2) { + uint8_t bitmask_l = bitmask & 0xff; + uint8_t bitmask_h = bitmask >> 8; + for (int i = 0; i < 8; i++) { + if (da2->writemask & (1 << i)) { + //da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]); + switch (da2->gdcreg[LG_COMMAND] & 0x03) + { + case 0: /*Set*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l); + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h); + da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 1: /*AND*/ + //da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i]; + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 2: /*OR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i]; + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 3: /*XOR*/ + //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i]; + //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + } + } + } +} + +static uint8_t da2_mmio_read(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + addr &= DA2_MASK_MMIO; + + if (da2->ioctl[LS_MMIO] & 0x10) { + if (da2->fctl[LF_MMIO_SEL] == 0x80) + //linear access + addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17); + else + { + //64k bank switch access + uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; + index <<= 8; + index |= da2->fctl[LF_MMIO_ADDR]; + addr += index * 0x40; + } + //da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { + case 0xb0://Gaiji RAM + addr &= DA2_MASK_GAIJIRAM;//safety access + //da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]); + return da2->mmio.ram[addr]; + break; + case 0x10://Font ROM + if (da2->mmio.charset == DA2_DCONFIG_CHARSET_HANT) { + if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; + if (addr >= 0x180000) addr -= 0x40000; /* The bank 12 (180000h-19ffffh) is beyond the available ROM address range, + but the Chinese font sub card actually has this alias, and is used by DOS T5.0. */ + } + if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; + //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); + return da2->mmio.font[addr]; + break; + default: + return DA2_INVALIDACCESS8;//invalid memory access + break; + } + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 or 256 color mode + { + cycles -= video_timing_read_b; + for (int i = 0; i < 8; i++) + da2->gdcla[i] = da2->vram[(addr << 3) | i];//read in byte + //da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); + if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 + uint8_t ret = 0; + + for (int i = 0; i < 8; i++) + { + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register + ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xff : 0); + } + return ~ret; + } + else return da2->gdcla[da2->readplane]; + } + else //text mode 3 + { + cycles -= video_timing_read_b; + return da2->vram[addr]; + } +} +static uint16_t da2_mmio_readw(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + if (da2->ioctl[LS_MMIO] & 0x10) { + return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + { + cycles -= video_timing_read_w; + addr &= DA2_MASK_MMIO; + for (int i = 0; i < 8; i++) + da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read vram into latch + +#ifdef ENABLE_DA2_DEBUGBLT + ////debug + //if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) + //{ + // fprintf(da2->mmrdbg_fp, "\nR %x ", addr); + // for (int i = 0; i <= 0xb; i++) + // fprintf(da2->mmrdbg_fp, "%02x ", da2->gdcreg[i]); + //} + //for (int i = 0; i < 16; i++) + //{ + // int pixeldata = 0; + // if (da2->gdcla[da2->readplane] & (1 << (15 - i))) pixeldata = 1; + // fprintf(da2->mmrdbg_fp, "%X", pixeldata); + //} + //da2->mmrdbg_vidaddr = addr; +#endif + + if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 + uint16_t ret = 0; + + for (int i = 0; i < 8; i++) + { + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register + ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xffff : 0); + } + return ~ret; + } + else + { + //da2_log("da2_Rw: %05x=%04x\n", addr, da2->gdcla[da2->readplane]); + return da2->gdcla[da2->readplane]; + } + } + else { + return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); + } +} + +static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //da2_log("da2_mmio_write %x %x\n", addr, val); + if ((addr & ~DA2_MASK_MMIO) != 0xA0000) return; + addr &= DA2_MASK_MMIO; + + if (da2->ioctl[LS_MMIO] & 0x10) { + //if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI); + //Gaiji RAM + if (da2->fctl[LF_MMIO_SEL] == 0x80) + addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17);//xxxy yyyy yyyy yyyy yyyy + else + { + uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; + index <<= 8; + index |= da2->fctl[LF_MMIO_ADDR]; + addr += index * 0x40; + } + switch (da2->fctl[LF_MMIO_MODE]) { + case 0xb0://Gaiji RAM 1011 0000 + addr &= DA2_MASK_GAIJIRAM;//safety access + da2->mmio.ram[addr] = val; + break; + case 0x10://Font ROM 0001 0000 + //Read-Only + break; + case 0x00: + //da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); + //addr &= 0x7f;//OS/2 write addr 1cf80-1cfc3, val xx + //if (addr >= DA2_BLT_MEMSIZE) + //{ + // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + // return; + //} + da2->bitblt.indata = 1; + if(da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) + da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_addr++; + break; + default: + da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + break; + } + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + { + uint8_t wm = da2->writemask; + //da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); +#ifdef ENABLE_DA2_DEBUGBLT + //debug + //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + //{ + if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) + { + fprintf(da2->mmdbg_fp, "\nB %x ", addr); + for (int i = 0; i <= 0xb; i++) + fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + } + for (int i = 0; i < 8; i++) + { + int pixeldata = 0; + if (val & (1 << (7 - i))) pixeldata = (da2->writemask & 0xf); + fprintf(da2->mmdbg_fp, "%X", pixeldata); + } + da2->mmdbg_vidaddr = addr; + //} +#endif + + cycles -= video_timing_write_b; + + da2->changedvram[addr >> 12] = changeframecount; + addr <<= 3; + + for (int i = 0; i < 8; i++) + da2->gdcsrc[i] = da2->gdcla[i];//use latch + + //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); + //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); + + if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; + else da2->gdcinput[i] = val; + da2_gdcropB(addr, da2); + return; + } + + switch (da2->writemode) + { + case 2: + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) da2->vram[addr | i] = da2->gdcsrc[i]; + break; + case 0: + if (da2->gdcreg[LG_DATA_ROTATION] & 7) + val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; + if (da2->gdcreg[LG_BIT_MASK_LOW] == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) da2->vram[addr | i] = val; + } + else + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + else da2->gdcinput[i] = val; + + for (int i = 0; i < 8; i++) + da2->debug_vramold[i] = da2->vram[addr | i];//use latch + da2_gdcropB(addr, da2); + //for (int i = 0; i < 8; i++) + // da2_log("\tsrc %02x in %02x bitm %02x mod %x rop %x: %02x -> %02x\n", da2->gdcsrc[i], da2->gdcinput[i], da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch + //// da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); + } + break; + case 1: + if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + } + else + { + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); + da2_gdcropB(addr, da2); + } + break; + case 3: + if (da2->gdcreg[LG_DATA_ROTATION] & 7) + val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; + wm = da2->gdcreg[LG_BIT_MASK_LOW]; + da2->gdcreg[LG_BIT_MASK_LOW] &= val; + + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + da2_gdcropB(addr, da2); + da2->gdcreg[LG_BIT_MASK_LOW] = wm; + break; + } + //da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); + } + else// mode 3h text + { + cycles -= video_timing_write_b; + da2->vram[addr] = val; + da2->fullchange = 2; + } +} +uint16_t rightRotate(uint16_t data, uint8_t count) +{ + return (data >> count) | (data << (sizeof(data) * 8 - count)); +} +static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + uint8_t wm = da2->writemask; + uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + bitmask <<= 8; + bitmask |= (uint16_t)da2->gdcreg[LG_BIT_MASK_LOW]; +#ifdef ENABLE_DA2_DEBUGBLT + //debug + //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + //{ + if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) + { + fprintf(da2->mmdbg_fp, "\nW %x ", addr); + for (int i = 0; i <= 0xb; i++) + fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + } + for (int i = 0; i < 16; i++) + { + int pixeldata = 0; + if (val & (1 << (15 - i))) pixeldata = (da2->writemask & 0xf); + fprintf(da2->mmdbg_fp, "%X", pixeldata); + } + da2->mmdbg_vidaddr = addr; + //} +#endif + cycles -= video_timing_write_w; + //cycles_lost += video_timing_write_w; + + //da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); + //da2_log("da2_gcW %05X %02X %04X:%04X esdi %04X:%04X dssi %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); + + da2->changedvram[addr >> 12] = changeframecount; + da2->changedvram[(addr + 1) >> 12] = changeframecount; + addr <<= 3; + + for (int i = 0; i < 8; i++) + da2->gdcsrc[i] = da2->gdcla[i];//use latch + + if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; + else da2->gdcinput[i] = val; + da2_gdcropW(addr, bitmask, da2); + return; + } + //da2_log("da2_Ww m%02x r%02x %05x:%04x=%02x%02x%02x%02x,%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] + // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); + switch (da2->writemode) + { + case 2: + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + { + da2->vram[addr | i] = da2->gdcsrc[i] & 0xff; + da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; + } + break; + case 0: + if (da2->gdcreg[LG_DATA_ROTATION] & 15) + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work + if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + { + da2->vram[addr | i] = val & 0xff; + da2->vram[(addr + 8) | i] = val >> 8; + } + } + else + { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + else da2->gdcinput[i] = val; + da2_gdcropW(addr, bitmask, da2); + // da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); + } + break; + case 1: + if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) + { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + { + uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + da2->vram[addr | i] = wdata & 0xff; + da2->vram[(addr + 8) | i] = wdata >> 8; + } + } + else + { + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); + da2_gdcropW(addr, bitmask, da2); + } + break; + case 3: + if (da2->gdcreg[LG_DATA_ROTATION] & 15) + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work + wm = bitmask; + bitmask &= val; + + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + da2_gdcropW(addr, bitmask, da2); + bitmask = wm; + break; + } + //da2_log("%02x%02x%02x%02x,%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] + // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); +} +static void da2_mmio_writew(uint32_t addr, uint16_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //if ((addr & ~0x1ffff) != 0xA0000) return; + if (da2->ioctl[LS_MMIO] & 0x10) { + //da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + da2_mmio_write(addr, val & 0xff, da2); + da2_mmio_write(addr + 1, val >> 8, da2); + } + else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + { + addr &= DA2_MASK_MMIO; + //return; + //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + da2_mmio_gc_writeW(addr, val, da2); + } + else {//mode 3h text + //if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); + //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + da2_mmio_write(addr, val & 0xff, da2); + da2_mmio_write(addr + 1, val >> 8, da2); + } +} + +static void da2_code_write(uint32_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //if ((addr & ~0xfff) != 0xE0000) return; + addr &= DA2_MASK_CRAM; + da2->cram[addr] = val; + da2->fullchange = 2; +} +static void da2_code_writeb(uint32_t addr, uint8_t val, void* p) +{ + da2_t* da2 = (da2_t*)p; + //da2_log("DA2_code_writeb: Write to %x, val %x\n", addr, val); + cycles -= video_timing_write_b; + da2_code_write(addr, val, da2); +} +static void da2_code_writew(uint32_t addr, uint16_t val, void* p) +{ + //da2_log("DA2_code_writew: Write to %x, val %x\n", addr, val); + da2_t* da2 = (da2_t*)p; + cycles -= video_timing_write_w; + da2_code_write(addr, val & 0xff, da2); + da2_code_write(addr + 1, val >> 8, da2); +} + +static uint8_t da2_code_read(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + if ((addr & ~DA2_MASK_CRAM) != 0xE0000) return DA2_INVALIDACCESS8; + addr &= DA2_MASK_CRAM; + return da2->cram[addr]; +} +static uint8_t da2_code_readb(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + cycles -= video_timing_read_b; + return da2_code_read(addr, da2); +} +static uint16_t da2_code_readw(uint32_t addr, void* p) +{ + da2_t* da2 = (da2_t*)p; + cycles -= video_timing_read_w; + return da2_code_read(addr, da2) | (da2_code_read(addr + 1, da2) << 8); + //return 0; +} + +void da2_doblit(int y1, int y2, int wx, int wy, da2_t* da2) +{ + 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; +} + +void da2_poll(void* priv) +{ + da2_t* da2 = (da2_t*)priv; + int x; + + if (!da2->linepos) + { + timer_advance_u64(&da2->timer, da2->dispofftime); + // if (output) printf("Display off %f\n",vidtime); + da2->cgastat |= 1; + da2->linepos = 1; + + if (da2->dispon) + { + da2->hdisp_on = 1; + + da2->ma &= da2->vram_display_mask; + if (da2->firstline == 2000) + { + da2->firstline = da2->displine; + video_wait_for_buffer(); + } + + if (!da2->override) + da2->render(da2); + + if (da2->lastline < da2->displine) + da2->lastline = da2->displine; + } + + //da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); + da2->displine++; + //if (da2->interlace) + // da2->displine++; + if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) + { + //da2_log("Vsync off at line %i\n",displine); + da2->cgastat &= ~8; + } + da2->vslines++; + if (da2->displine > 1200) + da2->displine = 0; + // da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], + // displine, vc, ma); + } + else + { + // da2_log("VC %i ma %05X\n", da2->vc, da2->ma); + timer_advance_u64(&da2->timer, da2->dispontime); + + // if (output) printf("Display on %f\n",vidtime); + if (da2->dispon) + da2->cgastat &= ~1; + da2->hdisp_on = 0; + + da2->linepos = 0; + if (da2->sc == (da2->crtc[LC_CURSOR_ROW_END] & 31)) + da2->con = 0; + if (da2->dispon) + { + if (da2->sc == da2->rowcount) + { + da2->linecountff = 0; + da2->sc = 0; + + da2->maback += (da2->rowoffset << 1);// color = 0x50(80), mono = 0x40(64) + if (da2->interlace) + da2->maback += (da2->rowoffset << 1); + da2->maback &= da2->vram_display_mask; + da2->ma = da2->maback; + } + else + { + da2->sc++; + da2->sc &= 31; + da2->ma = da2->maback; + } + } + + da2->vc++; + da2->vc &= 2047; + + if (da2->vc == da2->dispend) + { + da2->dispon = 0; + //if (da2->crtc[10] & 0x20) da2->cursoron = 0; + //else da2->cursoron = da2->blink & 16; + if (da2->ioctl[LS_MODE] & 1) {//in text mode + if (da2->attrc[LV_CURSOR_CONTROL] & 0x01)//cursor blinking + { + da2->cursoron = (da2->blink | 1) & da2->blinkconf; + } + else + { + da2->cursoron = 0; + } + if (!(da2->blink & (0x10 - 1)))//force redrawing for cursor and blink attribute + da2->fullchange = 2; + } + da2->blink++; + + for (x = 0; x < ((da2->vram_mask + 1) >> 12); x++) + { + if (da2->changedvram[x]) + da2->changedvram[x]--; + } + // memset(changedvram,0,2048); del + if (da2->fullchange) + { + da2->fullchange--; + } + } + if (da2->vc == da2->vsyncstart) + { + int wx, wy; + // da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); + da2->dispon = 0; + da2->cgastat |= 8; + x = da2->hdisp; + + //if (da2->interlace && !da2->oddeven) da2->lastline++; + //if (da2->interlace && da2->oddeven) da2->firstline--; + + wx = x; + wy = da2->lastline - da2->firstline; + + da2_doblit(da2->firstline_draw, da2->lastline_draw + 1, wx, wy, da2); + + da2->firstline = 2000; + da2->lastline = 0; + + da2->firstline_draw = 2000; + da2->lastline_draw = 0; + + da2->oddeven ^= 1; + + changeframecount = da2->interlace ? 3 : 2; + da2->vslines = 0; + + //if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch + (da2->rowoffset << 1) + ((da2->crtc[5] & 0x60) >> 5); + //else da2->ma = da2->maback = da2->ma_latch + ((da2->crtc[5] & 0x60) >> 5); + //da2->ca = ((da2->crtc[0xe] << 8) | da2->crtc[0xf]) + ((da2->crtc[0xb] & 0x60) >> 5) + da2->ca_adj; +/* if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch; + else*/ da2->ma = da2->maback = da2->ma_latch; + da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj; + + da2->ma <<= 1; + da2->maback <<= 1; + da2->ca <<= 1; + + // da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); + } + if (da2->vc == da2->vtotal) + { + // da2_log("VC vtotal\n"); + + + // printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); + da2->vc = 0; + da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; + da2->dispon = 1; + da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; + da2->scrollcache = da2->attrc[LV_PANNING] & 7; + } + if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) + da2->con = 1; + } + // printf("2 %i\n",da2_vsyncstart); + //da2_log("da2_poll %i %i %i %i %i %i %i\n", ins, da2->dispofftime, da2->dispontime, da2->vidtime, cyc_total, da2->linepos, da2->vc); + //da2_log("r"); +} + +static void da2_loadfont(char* fname, void* p) { + da2_t* da2 = (da2_t*)p; + uint8_t buf; + //uint32_t code = 0; + 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 > DA2_FONTROM_SIZE) { + fsize = DA2_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) { + fread(&buf, sizeof(uint8_t), 1, mfile); + da2->mmio.font[j] = buf; + j++; + } + fclose(mfile); + return; +} + +/* 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} +}; + +void da2_reset_ioctl(da2_t* da2) +{ + da2->ioctl[LS_RESET] = 0x00; /* Bit 0: Reset sequencer */ + da2_outw(LS_INDEX, 0x0302, da2); /* Index 02, Bit 1: VGA passthrough, Bit 0: Character Mode */ + da2_outw(LS_INDEX, 0x0008, da2); /* Index 08, Bit 0: Enable MMIO */ +} + +static void +da2_reset(void* priv) +{ + da2_t* da2 = (da2_t*)priv; + + /* Initialize drawing */ + da2->bitblt.exec = DA2_BLT_CIDLE; + da2->render = da2_render_blank; + da2_reset_ioctl(da2); + + da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ + da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ + da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ + da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA-II, 1024 KB */ + da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8 ) << 1); /* Configuration 1 : Monitor ID 3 */ + da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ + da2->fctl[0] = 0x2b; /* 3E3h:0 */ + da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ + da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ + da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ + da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ + da2->ma_latch = 0; + da2->interlace = 0; + da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ + da2->attr_palette_enable = 0; /* disable attribute generator */ + + /* Set default color palette (Windows 3.1 display driver won't reset palette) */ + da2_out(0x3c8, 0, da2); + for (int i = 0; i < 256; i++) { + da2_out(0x3c9, ps55_palette_color[i & 0x3F][0], da2); + da2_out(0x3c9, ps55_palette_color[i & 0x3F][1], da2); + da2_out(0x3c9, ps55_palette_color[i & 0x3F][2], da2); + } +} + +static void *da2_init() +{ + //Todo: init regs, gaiji memory, video memory, I/O handlers, font ROM + + if (svga_get_pri() == NULL) + return NULL; + svga_t *mb_vga = svga_get_pri(); + mb_vga->cable_connected = 0; + + da2_t* da2 = malloc(sizeof(da2_t)); + da2->mb_vga = mb_vga; + + da2->dispontime = 1000ull << 32; + da2->dispofftime = 1000ull << 32; + int memsize = 1024 * 1024; + da2->vram = malloc(memsize); + da2->vram_mask = memsize - 1; + da2->cram = malloc(0x1000); + da2->vram_display_mask = DA2_MASK_CRAM; + da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h + da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ + + da2->mmio.charset = device_get_config_int("charset"); + da2->mmio.font= malloc(DA2_FONTROM_SIZE); + switch(da2->mmio.charset) + { + case DA2_DCONFIG_CHARSET_HANT: + da2_loadfont(DA2_FONTROM_PATH_HANT, da2); + break; + case DA2_DCONFIG_CHARSET_JPAN: + da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); + break; + } + + mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); + da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ +#ifdef ENABLE_DA2_DEBUGBLT + da2->bitblt.debug_reg = malloc(DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE); + da2->mmdbg_fp = fopen("da2_mmiowdat.txt", "w"); + da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); + da2->bitblt.debug_reg_ip = 0; +#endif + da2->bitblt.payload_addr = 0; + da2_reset(da2); + + mem_mapping_add(&da2->mmio.mapping, 0xA0000, 0x20000, da2_mmio_read, da2_mmio_readw, NULL, da2_mmio_write, da2_mmio_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); + //da2_log("DA2mmio new mapping: %X, base: %x, size: %x\n", &da2->mmio.mapping, da2->mmio.mapping.base, da2->mmio.mapping.size); + + mem_mapping_disable(&da2->mmio.mapping); + + mem_mapping_add(&da2->cmapping, 0xE0000, 0x1000, da2_code_readb, da2_code_readw, NULL, da2_code_writeb, da2_code_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); + + mem_mapping_disable(&da2->cmapping); + + timer_add(&da2->timer, da2_poll, da2, 0); + da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ + timer_add(&da2->bitblt.timer, da2_bitblt_exec, da2, 0); + + return da2; +} +static int da2_available() +{ + return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); +} + +void da2_close(void *p) +{ + da2_t *da2 = (da2_t *)p; + + /* dump mem for debug */ +#ifndef RELEASE_BUILD + FILE* f; + f = fopen("da2_cram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->cram, 0x1000, 1, f); + fclose(f); + } + f = fopen("da2_vram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->vram, 1024*1024, 1, f); + fclose(f); + } + f = fopen("da2_gram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->mmio.ram, 256*1024, 1, f); + fclose(f); + } + f = fopen("da2_attrpal.dmp", "wb"); + if (f != NULL) { + fwrite(da2->attrc, 32, 1, f); + fclose(f); + } + f = fopen("da2_dacrgb.dmp", "wb"); + if (f != NULL) { + fwrite(da2->vgapal, 3*256, 1, f); + fclose(f); + } + f = fopen("da2_daregs.txt", "w"); + if (f != NULL) { + for (int i=0;i<0x10;i++) + fprintf(f, "3e1(ioctl) %02X: %4X\n", i, da2->ioctl[i]); + for (int i = 0; i < 0x20; i++) + fprintf(f, "3e3(fctl) %02X: %4X\n", i, da2->fctl[i]); + for (int i = 0; i < 0x20; i++) + fprintf(f, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); + for (int i = 0; i < 0x40; i++) + fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrc[i]); + for (int i = 0; i < 0x10; i++) + fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); + for (int i = 0; i < 0x10; i++) + fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); + fclose(f); + } +#endif +#ifdef ENABLE_DA2_DEBUGBLT + f = fopen("da2_bltdump.csv", "w"); + if (f != NULL && da2->bitblt.debug_reg_ip > 0) { + /* print header */ + for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { + if (da2->bitblt.debug_reg[(da2->bitblt.debug_reg_ip - 1) * DA2_DEBUG_BLTLOG_SIZE + y] != DA2_DEBUG_BLT_NEVERUSED) + fprintf(f, "\"%02X\"\t", y); + } + fprintf(f, "\n"); + /* print data */ + for (int x = 0; x < da2->bitblt.debug_reg_ip; x++) { + for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { + if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_NEVERUSED) + ; + else if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_USEDRESET) + fprintf(f, "\"\"\t"); + else + fprintf(f, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]); + } + fprintf(f, "\n"); + } + fclose(f); + } + if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); + if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); + free(da2->bitblt.debug_reg); +#endif + free(da2->cram); + free(da2->vram); + free(da2->changedvram); + free(da2->mmio.font); + free(da2); +} + +void da2_speed_changed(void *p) +{ + da2_t* da2 = (da2_t*)p; + da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); + da2_recalctimings(da2); +} + +void da2_force_redraw(void *p) +{ + da2_t* da2 = (da2_t*)p; + + da2->fullchange = changeframecount; +} + +static const device_config_t da2_configuration[] = { + // clang-format off + { + .name = "charset", + .description = "Charset", + .type = CONFIG_SELECTION, + .default_int = DA2_DCONFIG_CHARSET_JPAN, + .selection = { + { + .description = "932 (Japanese)", + .value = DA2_DCONFIG_CHARSET_JPAN + }, + { + .description = "938 (Traditional Chinese)", + .value = DA2_DCONFIG_CHARSET_HANT + }, + { .description = "" } + } + }, + { + .name = "montype", + .description = "Monitor type", + .type = CONFIG_SELECTION, + .default_int = DA2_DCONFIG_MONTYPE_COLOR, + .selection = { + { + .description = "Color", + .value = DA2_DCONFIG_MONTYPE_COLOR + }, + { + .description = "IBM 8515", + .value = DA2_DCONFIG_MONTYPE_8515 + }, + { + .description = "Grayscale", + .value = DA2_DCONFIG_MONTYPE_MONO + }, + { .description = "" } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ps55da2_device = { + .name = "IBM Display Adapter II (MCA)", + .internal_name = "ps55da2", + .flags = DEVICE_MCA, + .local = 0, + .init = da2_init, + .close = da2_close, + .reset = da2_reset, + { .available = da2_available }, + .speed_changed = da2_speed_changed, + .force_redraw = da2_force_redraw, + .config = da2_configuration +}; + +void +da2_device_add(void) +{ + if (!da2_standalone_enabled) + return; + + if (machine_has_bus(machine, MACHINE_BUS_MCA)) + device_add(&ps55da2_device); + else + return; +} From dc7e6c2d7fb2851f06d4a01847870f4fda05e600 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 11:05:16 +0900 Subject: [PATCH 39/82] Disabled DA2 debug logging by default --- src/video/vid_ps55da2.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 0ac136630..abbc3de16 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -228,10 +228,11 @@ #define LG_SET_RESET_2 0x10 #ifndef RELEASE_BUILD -#define ENABLE_DA2_LOG 1 +//#define ENABLE_DA2_LOG 1 #endif #ifdef ENABLE_DA2_LOG +#define ENABLE_DA2_DEBUGBLT 1 int da2_do_log = ENABLE_DA2_LOG; static void @@ -248,9 +249,6 @@ da2_log(const char* fmt, ...) #else # define da2_log(fmt, ...) #endif -#ifndef RELEASE_BUILD -# define ENABLE_DA2_DEBUGBLT 1 -#endif typedef struct da2_t { @@ -710,31 +708,35 @@ void da2_bitblt_load(da2_t* da2) // da2->bitblt.destpitch += 2; // da2->bitblt.srcpitch += 2; //} - uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; - uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2; da2->bitblt.destaddr += 2; da2->bitblt.srcpitch = 0; da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ da2->bitblt.bitshift_destr += 1; +#ifdef ENABLE_DA2_DEBUGBLT + uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); +#endif } else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { da2->bitblt.exec = DA2_BLT_CPUTCHAR; - uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; - uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; da2->bitblt.destaddr += 2; da2->bitblt.srcpitch = 0; da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ da2->bitblt.bitshift_destr += 1; +#ifdef ENABLE_DA2_DEBUGBLT + uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; + uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); +#endif } else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {/* Fill a rectangle(or draw a line) */ da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", @@ -898,15 +900,15 @@ void da2_bitblt_exec(void* p) case DA2_BLT_CPUTCHAR: //da2->bitblt.y += 2; da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; - pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); + //pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); //da2->bitblt.srcaddr += 2; if(da2->bitblt.reg[0x12] < 0x100) da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; else da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; - print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); - print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); - pclog("\n"); + //print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); + //print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); + //pclog("\n"); if (da2->bitblt.x >= da2->bitblt.size_x - 1) { //if (1) { DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); @@ -3059,7 +3061,7 @@ void da2_close(void *p) da2_t *da2 = (da2_t *)p; /* dump mem for debug */ -#ifndef RELEASE_BUILD +#ifdef ENABLE_DA2_LOG FILE* f; f = fopen("da2_cram.dmp", "wb"); if (f != NULL) { From a850821ecb5a01d73fbcb9e9225b6185a67586e7 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 11:29:44 +0900 Subject: [PATCH 40/82] updated comment in monitor detection (vid_svga .c) --- src/video/vid_svga.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index ef6381598..5d0db103b 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -511,10 +511,12 @@ svga_in(uint16_t addr, void *priv) } else { - // The Display Adapter has own Monitor Type Detection bit in the different I/O port (I/O 3E0h, 3E1h). - // When the monitor cable is connected to the Display Adapter, this port returns the value as no cable connection. - // The Power-on Self Test of PS/55 tries detecting the monitor on the planar VGA. - // If it fails, then the POST reads the NVRAM set by the reference diskette, and sets the BIOS Data Area (Mem 487h, 489h). + /* + The IBM PS/55 Display Adapter has own Monitor Type Detection bit in the different I/O port (I/O 3E0h, 3E1h). + When the monitor cable is connected to the Display Adapter, this port returns the value as 'no cable connection'. + The POST of PS/55 has an extra code that tries detecting the monitor on the planar VGA. + If it fails, then the POST reads the NVRAM set by the reference diskette, and updates the BIOS Data Area (Mem 487h, 489h). + */ if (svga->vgapal[0].r >= 10 || svga->vgapal[0].g >= 10 || svga->vgapal[0].b >= 10) ret = 0; else From aa7d5d2dc2c4cd7b58dfdf1d478c176a63f41f0d Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 11:49:26 +0900 Subject: [PATCH 41/82] removed unused device decl --- src/floppy/fdc.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 75c2c10af..243df4ca5 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -722,7 +722,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) if ((val & 4) && !(fdc->dor & 4)) fdc_soft_reset(fdc); /* We can now simplify this since each motor now spins separately. */ - for (int i = 0; i < FDD_NUM; i++) { + for (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); @@ -2612,20 +2612,6 @@ const device_t fdc_at_actlow_device = { .config = NULL }; -const device_t fdc_at_ps2_device = { - .name = "PC/AT Floppy Drive Controller (PS/2 internal)", - .internal_name = "fdc_at_ps55", - .flags = 0, - .local = FDC_FLAG_AT | FDC_FLAG_PS2, - .init = fdc_init, - .close = fdc_close, - .reset = fdc_reset, - {.available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - const device_t fdc_at_smc_device = { .name = "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)", .internal_name = "fdc_at_smc", From 16fc5e79020a2b65f3126d6a80d8c65dbe7e1aba Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 12:08:50 +0900 Subject: [PATCH 42/82] corrected compile errors, removed garbage --- src/disk/hdc_esdi_mca.c | 2 +- src/floppy/fdc.c | 21 +-------------------- src/machine/m_ps2_mca.c | 6 +++--- src/video/vid_ps55da2.c | 2 +- 4 files changed, 6 insertions(+), 25 deletions(-) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 5656181f0..5b471b754 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1514,7 +1514,7 @@ esdi_integrated_device = { .init = esdi_init, .close = esdi_close, .reset = esdi_reset, - {.available = NULL }, + .available = esdi_available, .speed_changed = NULL, .force_redraw = NULL, .config = esdi_integrated_config diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 243df4ca5..1692a7aaa 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -722,7 +722,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) if ((val & 4) && !(fdc->dor & 4)) fdc_soft_reset(fdc); /* We can now simplify this since each motor now spins separately. */ - for (i = 0; i < FDD_NUM; i++) { + 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); @@ -1284,25 +1284,6 @@ fdc_read(uint16_t addr, void *priv) if (fdc->fintr || fdc->reset_stat) /* INTR */ ret |= 0x80; } - else if (fdc->flags & FDC_FLAG_PS2) { - /* Status Register A (PS/2, PS/55) */ - /* | INT PEND | nDRV2 | STEP | nTRK0 | HDSEL | nIDX | nWP | DIR | */ - ret = 0x04; - if (!fdc->seek_dir) /* DIRECTION */ - ret |= 0x01; - if (!writeprot[drive]) /* nWRITEPROT */ - ret |= 0x02; - if (fdd_get_head(drive)) /* HDSEL */ - ret |= 0x08; - if (!fdd_track0(drive)) /* nTRK0 */ - ret |= 0x10; - if (fdc->step) /* STEP */ - ret |= 0x20; - if (!fdd_get_type(1)) /* -Drive 2 Installed */ - ret |= 0x40; - if (fdc->fintr || fdc->reset_stat) /* INTR */ - ret |= 0x80; - } else ret = 0xff; break; diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index c355ba4b2..b948c984c 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -780,13 +780,13 @@ ps55_model_50tv_write(uint16_t port, uint8_t val) switch ((val >> 5) & 3) { case 0: - lpt1_init(LPT_MDA_ADDR); + lpt1_setup(LPT_MDA_ADDR); break; case 1: - lpt1_init(LPT1_ADDR); + lpt1_setup(LPT1_ADDR); break; case 2: - lpt1_init(LPT2_ADDR); + lpt1_setup(LPT2_ADDR); break; default: break; diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index abbc3de16..98b827421 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -3205,7 +3205,7 @@ const device_t ps55da2_device = { .init = da2_init, .close = da2_close, .reset = da2_reset, - { .available = da2_available }, + .available = da2_available, .speed_changed = da2_speed_changed, .force_redraw = da2_force_redraw, .config = da2_configuration From db056e0b66ee0262c8db06aada25b39829a98720 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 16:44:07 +0900 Subject: [PATCH 43/82] fixed a floppy drive access issue It took a few hours that I noticed fdc.c decides the floppy drive type by the machine name. --- src/floppy/fdc.c | 10 ++++------ src/floppy/fdd.c | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 1692a7aaa..7f025df2d 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -743,7 +743,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) /* Bit 2: FIFO test mode (PS/55 only? This is not documented in neither the PS/2 HITR nor the 82077AA datasheet.) The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h. If it fails, then floppy drives will be treated as DD drives. */ - if (fdc->flags & FDC_FLAG_PS2) { + if (fdc->flags & FDC_FLAG_PS2_MCA) { if (val & 0x04) { fdc->tfifo = 8; @@ -769,6 +769,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 5: /*Command register*/ 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); fifo_write(val, fdc->fifo_p); if (fifo_get_full(fdc->fifo_p)) @@ -1358,10 +1359,7 @@ fdc_read(uint16_t addr, void *priv) ret = 0x10; else ret = 0x00; - } - else if (fdc->flags & FDC_FLAG_PS2) { - /* error when ret = 1, 2*/ - ret = (fdc->fifointest) ? 4 : 0; + /* PS/55 POST throws an error and halt if ret = 1 or 2, somehow. */ } else if (!fdc->enh_mode) ret = 0x20; @@ -1374,6 +1372,7 @@ fdc_read(uint16_t addr, void *priv) case 5: /*Data*/ if (fdc->fifointest) { + /* Read FIFO buffer in the test mode (PS/55) */ ret = fifo_read(fdc->fifo_p); break; } @@ -1698,7 +1697,6 @@ fdc_callback(void *priv) else if (fdc->params[5] == 0) fdc->sector++; ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); - //fdc_log("cb_rwsect: %d %d %d %d %d %xh\n", real_drive(fdc, fdc->drive), fdc->sector, fdc->rw_track, fdc->head, fdc->rate, fdc->params[4]); switch (fdc->interrupt) { case 5: case 9: diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index f0a32df75..d3d513b9f 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -294,7 +294,7 @@ fdd_type_invert_densel(int type) int ret; if (drive_types[type].flags & FLAG_PS2) - ret = (!!strstr(machine_getname(), "PS/1")) || (!!strstr(machine_getname(), "PS/2")); + ret = (!!strstr(machine_getname(), "PS/1")) || (!!strstr(machine_getname(), "PS/2")) || (!!strstr(machine_getname(), "PS/55")); else ret = drive_types[type].flags & FLAG_INVERT_DENSEL; From 75ccfc6e2dfccde089a8b47476c24fcc6f94eb0b Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 16:58:11 +0900 Subject: [PATCH 44/82] Integrated ESDI doesn't need an external ROM --- src/disk/hdc.c | 2 +- src/disk/hdc_esdi_mca.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 3ec6358d8..f09a9a430 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -77,7 +77,7 @@ static const struct { { &xtide_acculogic_device }, { &xtide_device }, { &esdi_ps2_device }, - { &esdi_integrated_device }, + { &esdi_integrated_device }, { &ide_pci_device }, { &ide_pci_2ch_device }, { &ide_vlb_device }, diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 5b471b754..df2a26349 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1514,7 +1514,7 @@ esdi_integrated_device = { .init = esdi_init, .close = esdi_close, .reset = esdi_reset, - .available = esdi_available, + .available = NULL, /* The Disk BIOS is included in the System ROM */ .speed_changed = NULL, .force_redraw = NULL, .config = esdi_integrated_config From 3a09622a91c6b25d7f10425f731a07926873cdb9 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 17:36:00 +0900 Subject: [PATCH 45/82] added switching ca keys by kbd scancode set --- src/86box.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/86box.c b/src/86box.c index 764f707ba..1cd0ffec8 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1094,14 +1094,24 @@ pc_init_modules(void) void pc_send_ca(uint16_t sc) { - /* Use R-Alt because PS/55 DOS assigns L-Alt as Kanji */ - keyboard_input(1, 0x1D); /* Ctrl key pressed */ - keyboard_input(1, 0x138); /* R-Alt key pressed */ - keyboard_input(1, sc); - usleep(50000); - keyboard_input(0, sc); - keyboard_input(0, 0x138); /* R-Alt key released */ - keyboard_input(0, 0x1D); /* Ctrl key released */ + if (keyboard_mode == 0x8A) { + /* Use R-Alt because PS/55 DOS assigns L-Alt Kanji */ + keyboard_input(1, 0x1D); /* Ctrl key pressed */ + keyboard_input(1, 0x138); /* R-Alt key pressed */ + keyboard_input(1, sc); + usleep(50000); + keyboard_input(0, sc); + keyboard_input(0, 0x138); /* R-Alt key released */ + keyboard_input(0, 0x1D); /* Ctrl key released */ + } else { + keyboard_input(1, 0x1D); /* Ctrl key pressed */ + keyboard_input(1, 0x38); /* Alt key pressed */ + keyboard_input(1, sc); + usleep(50000); + keyboard_input(0, sc); + keyboard_input(0, 0x38); /* Alt key released */ + keyboard_input(0, 0x1D); /* Ctrl key released */ + } } /* Send the machine a Control-Alt-DEL sequence. */ From dbeaa2a56b122d175202721ba8efd8cea3a6212e Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 17:38:24 +0900 Subject: [PATCH 46/82] minor update in comparison table --- src/device/keyboard_at.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index b78fbd653..5c66029ad 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -1648,14 +1648,14 @@ static const scancode scancode_set3[512] = { Currently, scancode set 81h and 82h are not implemented yet. Also, the key layout is designed to match with the Japanese keyboard. - [Japanese DOS and keyboard scancode set] - | | K3.3 | J4.0 | J5.0 | J4.0/V | J5.0/V | OS/2 J1.3 | PC DOS 5 | + [Japanese DOS and keyboard scancode set comparison] + | | K3.3 | J4.0 | J5.0 | J4.0/V | J5.0/V | OS/2 J1.3 | DOS 5(US)| |---------------------------|:----:|:----:|:----:|:------:|:------:|:---------:|:--------:| | IBM 101-key | n/a | n/a | n/a | n/a | 2 | n/a | 2 | - | IBM-J 5576-00x (obsolete) | 8A | 8A | 8A | 82 | 82 | 82 | 2 | - | OADG (modern JA standard) | n/a | n/a | n/a | 2 | 2 | 2 | 2 | */ + | IBM-J 5576-00x (obsolete) | 8Ah | 8Ah | 8Ah | 82h | 82h | 82h | 2 | + | OADG (modern Japanese) | n/a | n/a | n/a | 2 | 2 | 2 | 2 | */ -/* Scancode set 8Ah : 5556 keyboard compatible scancode set used by J-DOS */ +/* Scancode set 8Ah : IBM 5556 keyboard compatible scancode set used by J-DOS */ static scancode scancode_set8a[512] = { // clang-format off From 1c7a8e5bbba516fc50b4c91f81fde3521bad3994 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 18:32:12 +0900 Subject: [PATCH 47/82] updated comments, modified format --- src/video/vid_ps55da2.c | 336 ++++++++++++++++++++-------------------- 1 file changed, 170 insertions(+), 166 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 98b827421..5098fa64d 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -6,11 +6,11 @@ * * This file is part of the 86Box distribution. * - * IBM PS/55 Display Adapter II emulation. + * IBM PS/55 Display Adapter II (and its successors) emulation. * * Authors: Akamaki. * - * Copyright 2024 Akamaki. + * Copyright 2024-2025 Akamaki. */ #include @@ -58,6 +58,8 @@ #define DA2_DCONFIG_CHARSET_JPAN 0 /* for Code page 932 Japanese */ //#define DA2_DCONFIG_CHARSET_HANG 1 /* for Code page 934 Hangul */ //#define DA2_DCONFIG_CHARSET_HANS 2 /* for Code page 936 Simplified Chinese */ +/* These ROMs are currently not found. + At least, IBM-J released a Korean and PRC version of PS/55 for each market. */ #define DA2_DCONFIG_CHARSET_HANT 3 /* for Code page 938 Traditional Chinese */ #define DA2_DCONFIG_MONTYPE_COLOR 0x0A #define DA2_DCONFIG_MONTYPE_8515 0x0B @@ -108,21 +110,23 @@ #define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ //#define Mon_ID3 0x10 #define FontCard 0x08 /* ? */ -/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode is not supported). */ #define Page_One 0x06 /* 80000h 110b */ #define Page_Two 0x05 /* 100000h 101b */ #define Page_Four 0x03 /* 200000h 011b */ +/* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode unsupported). */ /* IO 3E0/3E1:0Bh Hardware Configuration Value H (imported from OS/2 DDK) */ #define AddPage 0x08 /* ? */ //#define Mon_ID2 0x04 //#define Mon_ID1 0x02 //#define Mon_ID0 0x01 -/* Monitor ID (imported from OS/2 DDK 1.2) */ -//#define StarbuckC 0x0A //1 010b IBM 8514, 9518 color 1040x768 -//#define StarbuckM 0x09 //1 001b IBM 8507, 8604 grayscale -//#define Lark_B 0x02 //0 010b IBM 9517 color 1040x768 but 4bpp -//#define Dallas 0x0B //1 011b IBM 8515, 9515 color 1040x740 palette B + +/* Monitor ID (imported from OS/2 DDK 1.2) +#define StarbuckC 0x0A // 1 010b IBM 8514, 9518 color 1040x768 +#define StarbuckM 0x09 // 1 001b IBM 8507, 8604 grayscale +#define Lark_B 0x02 // 0 010b IBM 9517 color 1040x768 but 4bpp +#define Dallas 0x0B // 1 011b IBM 8515, 9515 color 1040x740 another palette +*/ /* DA2 Registers (imported from OS/2 DDK) */ #define AC_REG 0x3EE @@ -467,9 +471,9 @@ void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel void DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t* da2) { pixel32 srcpx; - //fill data with input color + /* fill data with input color */ for (int i = 0; i < 8; i++) - srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0;//read in word + srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0;/* read in word */ DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } @@ -494,7 +498,6 @@ Param Desc 2B Tile Addr 33 Size W 35 Size H - */ void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) { @@ -505,7 +508,7 @@ void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t srcpx.p8[i] = DA2_readvram_s((srcaddr + 24) | i, da2) | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) - | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24);//read in word + | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24); DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } @@ -520,7 +523,7 @@ void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, srcpx.p8[i] = ((uint32_t)da2->mmio.font[srcaddr] << 24) | ((uint32_t)da2->mmio.font[srcaddr + 1] << 16) | ((uint32_t)da2->mmio.font[srcaddr + 2] << 8) - | ((uint32_t)da2->mmio.font[srcaddr + 3] << 0);//read in word + | ((uint32_t)da2->mmio.font[srcaddr + 3] << 0); DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } @@ -666,8 +669,8 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.debug_reg_ip++; if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; #endif - da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f);//set bit shift - da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03;//01 AND, 03 XOR + da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f);/* set bit shift */ + da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03;/* 01 AND, 03 XOR */ da2_log("bitblt execute 05: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); for (int i = 0; i <= 0xb; i++) da2_log("%02x ", da2->gdcreg[i]); @@ -678,7 +681,7 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.size_y = da2->bitblt.reg[0x35]; da2->bitblt.destpitch = da2->bitblt.reg[0x21]; da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; - if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; + if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ { da2->bitblt.destaddr -= 2; da2->bitblt.size_x += 1; @@ -693,7 +696,7 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.exec = DA2_BLT_CDONE; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - if (da2->bitblt.reg[0x2f] < 0x80)//MS Paint 3.1 will cause hang up in 256 color mode + if (da2->bitblt.reg[0x2f] < 0x80) /* MS Paint 3.1 will cause hang up in 256 color mode */ { da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); da2->bitblt.exec = DA2_BLT_CDONE; @@ -701,7 +704,7 @@ void da2_bitblt_load(da2_t* da2) else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ da2->bitblt.exec = DA2_BLT_CPUTCHAR; /* Todo: addressing */ - //if (da2->bitblt.reg[0x2F] == 0x90) //destaddr -= 2, length += 1; + //if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ //{ // da2->bitblt.destaddr += 2; // da2->bitblt.size_x -= 1; @@ -738,14 +741,16 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); #endif } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) {/* Fill a rectangle(or draw a line) */ + /* Fill a rectangle(or draw a line) */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); da2->bitblt.exec = DA2_BLT_CFILLRECT; da2->bitblt.destaddr += 2; } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */ + /* Tiling a rectangle ??(transfer tile data multiple times) os/2 only */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x0040 && da2->bitblt.reg[0x3D] == 0x40) { da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; @@ -756,7 +761,8 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) {/* Tiling a rectangle (transfer tile data multiple times) */ + /* Tiling a rectangle (transfer tile data multiple times) */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) { da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; @@ -767,7 +773,8 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) {/* Block transfer (range copy) */ + /* Block transfer (range copy) */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) { da2->bitblt.exec = DA2_BLT_CCOPYF; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr += 2; @@ -777,7 +784,8 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) {/* Block copy but reversed direction */ + /* Block copy but reversed direction */ + else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) { da2->bitblt.exec = DA2_BLT_CCOPYR; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr -= 2; @@ -1245,7 +1253,7 @@ uint16_t da2_in(uint16_t addr, void *p) temp = da2->ioctladdr; break; case LS_DATA: - //da2->ioctl[3] = 0x80;//3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) + //da2->ioctl[3] = 0x80; /* 3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) */ if (da2->ioctladdr > 0xf) return DA2_INVALIDACCESS8; temp = da2->ioctl[da2->ioctladdr]; if (da2->ioctladdr == LS_STATUS) { /* Status register */ @@ -1304,7 +1312,7 @@ uint16_t da2_in(uint16_t addr, void *p) temp = da2->attraddr | da2->attr_palette_enable; break; case 0x3E9: - if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this may equiv to 3ba / 3da Input Status Register 1 */ + if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this maybe equivalent to 3ba / 3da Input Status Register 1 */ { if (da2->cgastat & 0x01) da2->cgastat &= ~0x30; @@ -1587,23 +1595,23 @@ The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh. uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void* p) { da2_t* da2 = (da2_t*)p; uint32_t font = 0; - int32_t fline = line - 2;//Start line of drawing character (line >= 1 AND line < 24 + 1 ) - if (code >= 0x8000 && code <= 0x8183) code -= 0x6000;//shift for IBM extended characters (I don't know how the real card works.) + int32_t fline = line - 2;/* Start line of drawing character (line >= 1 AND line < 24 + 1 ) */ + if (code >= 0x8000 && code <= 0x8183) code -= 0x6000;//shift for IBM extended characters (I don't know how the real card works.) */ if (code < DA2_FONTROM_SIZE / 72 && fline >= 0 && fline < 24) { - font = da2->mmio.font[code * 72 + fline * 3]; //1111 1111 - font <<= 8; //1111 1111 0000 0000 - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; //1111 1111 2222 0000 - font >>= 1; //0111 1111 1222 2000 - font <<= 4; //0111 1111 1222 2000 0000 - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; //0111 1111 1222 2000 2222 - font <<= 8; //0111 1111 1222 2000 2222 0000 0000 - font |= da2->mmio.font[code * 72 + fline * 3 + 2]; //0111 1111 1222 2000 2222 3333 3333 - font <<= 4; //0111 1111 1222 2000 2222 3333 3333 0000 - //font >>= 1;//put blank at column 1 (and 26) + font = da2->mmio.font[code * 72 + fline * 3]; /* 1111 1111 */ + font <<= 8; /* 1111 1111 0000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; /* 1111 1111 2222 0000 */ + font >>= 1; /* 0111 1111 1222 2000 */ + font <<= 4; /* 0111 1111 1222 2000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; /* 0111 1111 1222 2000 2222 */ + font <<= 8; /* 0111 1111 1222 2000 2222 0000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 2]; /* 0111 1111 1222 2000 2222 3333 3333 */ + font <<= 4; /* 0111 1111 1222 2000 2222 3333 3333 0000 */ + /* font >>= 1;//put blank at column 1 (and 26) */ } else if (code >= 0xb000 && code <= 0xb75f) { - //convert code->address in gaiji memory + /* convert code->address in gaiji memory */ code -= 0xb000; code *= 0x80; //code += 0xf800; @@ -1631,11 +1639,11 @@ uint8_t IRGBtoBGRI(uint8_t attr) /* Get the foreground color from the attribute byte */ uint8_t getPS55ForeColor(uint8_t attr, da2_t* da2) { - uint8_t foreground = ~attr & 0x08;// 0000 1000 - foreground <<= 2; //0010 0000 - foreground |= ~attr & 0xc0;// 1110 0000 - foreground >>= 4;//0000 1110 - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;//bright color palette + uint8_t foreground = ~attr & 0x08;// 0000 1000 */ + foreground <<= 2; /* 0010 0000 */ + foreground |= ~attr & 0xc0;/* 1110 0000 */ + foreground >>= 4;/* 0000 1110 */ + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;/* bright color palette */ return foreground; } @@ -1675,104 +1683,104 @@ static void da2_render_text(da2_t* da2) chr = da2->cram[(da2->ma) & da2->vram_display_mask]; attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; //if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80)//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) + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80)/* 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, da2); - if (attr & 0x04) {//reverse 0000 0100 + 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 + {/* --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 + 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 + attr &= 0x33;/* disable blinkking, underscore, highlight and reverse */ } - if (attr & 0x04) {//reverse 0000 0100 + if (attr & 0x04) {/* reverse 0000 0100 */ bg = fg; fg = 0; } - // Blinking 1000 0000 + /* Blinking 1000 0000 */ fg = ((da2->blink & 0x20) || (!(attr & 0x80))) ? fg : bg; //if(chr!=0x20) da2_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, da2->egapal[fg], da2->pallook[da2->egapal[fg]]); } - //Draw character - for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank - // SBCS or DBCS left half + /* Draw character */ + for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->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. + /* 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 + /* Get high DBCS code from the next video address */ chr_dbcs = da2->cram[((da2->ma) + 2) & da2->vram_display_mask]; chr_dbcs <<= 8; chr_dbcs |= chr; - // Get the font pattern + /* Get the font pattern */ uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots + /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; font <<= 1; } } else { - // the char code is SBCS (ANK) + /* the char code is SBCS (ANK) */ uint32_t fontbase; - if (attr & 0x02)//second map of SBCS font + if (attr & 0x02)/* second map of SBCS font */ fontbase = DA2_GAIJIRAM_SBEX; else fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];/* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];/* w13xh29 font */ //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); - // Draw 13 dots + /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; font <<= 1; } } } - // right half of DBCS + /* right half of DBCS */ else { uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots + /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; font <<= 1; } chr_wide = 0; } - //Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. - if (da2->sc == 27 && attr & 0x40 && ~da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) {//Underscore only in monochrome mode + /* Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. */ + if (da2->sc == 27 && attr & 0x40 && ~da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) {/* Underscore only in monochrome mode */ for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[fg]];//under line (white) + p[n] = da2->pallook[da2->egapal[fg]];/* under line (white) */ } - //Column 1 (Vertical Line) + /* Column 1 (Vertical Line) */ if (attr & 0x10) { - p[0] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];//vertical line (white) + p[0] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];/* vertical line (white) */ } - if (da2->sc == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) {//HGrid + if (da2->sc == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) {/* HGrid */ for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];//horizontal line (white) + p[n] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];/* horizontal line (white) */ } - //Drawing text cursor + /* Drawing text cursor */ drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) { int cursorwidth = (da2->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); - int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2;//Choose color 2 if mode 8 + int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2;/* Choose color 2 if mode 8 */ fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2); bg = 0; - if (attr & 0x04) {//Color 0 if reverse + if (attr & 0x04) {/* Color 0 if reverse */ bg = fg; fg = 0; } @@ -1820,32 +1828,32 @@ static void da2_render_textm3(da2_t* da2) fg = attr & 0xf; fg = IRGBtoBGRI(fg); bg = IRGBtoBGRI(bg); - //Draw character - for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];//draw blank - // SBCS or DBCS left half + /* Draw character */ + for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];/* draw blank */ + /* BCS or DBCS left half */ if (chr_wide == 0) { if (extattr & 0x01) chr_wide = 1; - // Stay drawing if the char code is DBCS and not at last column. + /* 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 + /* Get high DBCS code from the next video address */ chr_dbcs = da2->vram[(0x18000 + (da2->ma) + 2) & da2->vram_mask]; chr_dbcs <<= 8; chr_dbcs |= chr; - // Get the font pattern + /* Get the font pattern */ uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots + /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; font <<= 1; } } else { - // the char code is SBCS (ANK) + /* the char code is SBCS (ANK) */ uint32_t fontbase; fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];// w13xh29 font + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];/* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];// w13xh29 font + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];/* w13xh29 font */ //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; @@ -1853,26 +1861,25 @@ static void da2_render_textm3(da2_t* da2) } } } - // right half of DBCS + /* right half of DBCS */ else { uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); - // Draw 13 dots + /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; font <<= 1; } chr_wide = 0; } - //Drawing text cursor drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) { //int cursorwidth = (da2->crtc[0x1f] & 0x20 ? 26 : 13); - //int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;//Choose color 2 if mode 8 + //int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;/* Choose color 2 if mode 8 */ //fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; //bg = 0; - //if (attr & 0x04) {//Color 0 if reverse + //if (attr & 0x04) {/* Color 0 if reverse */ // bg = fg; // fg = 0; //} @@ -1891,7 +1898,7 @@ void da2_render_color_4bpp(da2_t* da2) { int changed_offset = da2->ma >> 12; //da2_log("ma %x cf %x\n", da2->ma, changed_offset); - da2->plane_mask &= 0x0f;//safety + da2->plane_mask &= 0x0f; /*safety */ if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) { @@ -1904,12 +1911,12 @@ void da2_render_color_4bpp(da2_t* da2) da2->lastline_draw = da2->displine; //da2_log("d %X\n", da2->ma); - for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 + for (x = 0; x <= da2->hdisp; x += 8)/* hdisp = 1024 */ { uint8_t edat[8]; uint8_t dat; - //get 8 pixels from vram + /* get 8 pixels from vram */ da2->ma &= da2->vram_display_mask; *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); da2->ma += 1; @@ -1952,7 +1959,7 @@ void da2_render_color_8bpp(da2_t* da2) da2->lastline_draw = da2->displine; //da2_log("d %X\n", da2->ma); - for (x = 0; x <= da2->hdisp; x += 8)//hdisp = 1024 + for (x = 0; x <= da2->hdisp; x += 8) /* hdisp = 1024 */ { uint8_t edat[8]; uint8_t dat; @@ -2037,7 +2044,7 @@ void da2_recalctimings(da2_t* da2) da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; da2->htotal += 1; - da2->rowoffset = da2->crtc[LC_OFFSET];//number of bytes in a scanline + da2->rowoffset = da2->crtc[LC_OFFSET];/* number of bytes in a scanline */ da2->clock = da2->da2const; @@ -2052,11 +2059,12 @@ void da2_recalctimings(da2_t* da2) da2->hdisp_time = da2->hdisp; da2->render = da2_render_blank; - //determine display mode + /* determine display mode */ //if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) if (da2->attrc[LV_COMPATIBILITY] & 0x08) { - if (!(da2->ioctl[LS_MODE] & 0x01)) {//16 color graphics mode + /* 16 color graphics mode */ + if (!(da2->ioctl[LS_MODE] & 0x01)) { da2->hdisp *= 16; da2->char_width = 13; da2->hdisp_old = da2->hdisp; @@ -2065,19 +2073,21 @@ void da2_recalctimings(da2_t* da2) da2->render = da2_render_color_8bpp; da2->vram_display_mask = DA2_MASK_GRAM; } - else {//PS/55 8-color + else {/* PS/55 8-color */ da2_log("Set videomode to PS/55 4 bpp graphics.\n"); da2->vram_display_mask = DA2_MASK_GRAM; da2->render = da2_render_color_4bpp; } } - else {//text mode + else { + /* text mode */ if (da2->attrc[LV_ATTRIBUTE_CNTL] & 1) { da2_log("Set videomode to PS/55 Mode 03 text.\n"); da2->render = da2_render_textm3; da2->vram_display_mask = DA2_MASK_CRAM; } - else {//PS/55 text(color/mono) + /* PS/55 text(color/mono) */ + else { da2_log("Set videomode to PS/55 Mode 8/E text.\n"); da2->render = da2_render_text; da2->vram_display_mask = DA2_MASK_CRAM; @@ -2096,7 +2106,7 @@ void da2_recalctimings(da2_t* da2) //da2->render = da2_draw_text; //} - // da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); + //da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); //if (da2->recalctimings_ex) // da2->recalctimings_ex(da2); @@ -2122,10 +2132,10 @@ void da2_recalctimings(da2_t* da2) if (da2->dispofftime < TIMER_USEC) da2->dispofftime = TIMER_USEC; da2_log("da2 horiz total %i display end %i vidclock %f\n",da2->crtc[0],da2->crtc[1],da2->clock); - // da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart); - // da2_log("total %f on %i cycles off %i cycles frame %i sec %i\n",disptime*crtcconst,da2->dispontime,da2->dispofftime,(da2->dispontime+da2->dispofftime)*da2->vtotal,(da2->dispontime+da2->dispofftime)*da2->vtotal*70); + //da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart); + //da2_log("total %f on %i cycles off %i cycles frame %i sec %i\n",disptime*crtcconst,da2->dispontime,da2->dispofftime,(da2->dispontime+da2->dispofftime)*da2->vtotal,(da2->dispontime+da2->dispofftime)*da2->vtotal*70); - // da2_log("da2->render %08X\n", da2->render); + //da2_log("da2->render %08X\n", da2->render); } uint8_t da2_mca_read(int port, void *p) @@ -2189,7 +2199,7 @@ static void da2_mca_reset(void *p) da2_reset(da2); da2_mca_write(0x102, 0, da2); } -// + static void da2_gdcropB(uint32_t addr, da2_t* da2) { for (int i = 0; i < 8; i++) { if (da2->writemask & (1 << i)) { @@ -2265,11 +2275,11 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) if (da2->ioctl[LS_MMIO] & 0x10) { if (da2->fctl[LF_MMIO_SEL] == 0x80) - //linear access + /* linear access */ addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17); else { - //64k bank switch access + /* 64k bank switch access */ uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; index <<= 8; index |= da2->fctl[LF_MMIO_ADDR]; @@ -2277,12 +2287,12 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) } //da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { - case 0xb0://Gaiji RAM - addr &= DA2_MASK_GAIJIRAM;//safety access + case 0xb0:/* Gaiji RAM */ + addr &= DA2_MASK_GAIJIRAM;/* safety access */ //da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]); return da2->mmio.ram[addr]; break; - case 0x10://Font ROM + case 0x10:/* Font ROM */ if (da2->mmio.charset == DA2_DCONFIG_CHARSET_HANT) { if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; if (addr >= 0x180000) addr -= 0x40000; /* The bank 12 (180000h-19ffffh) is beyond the available ROM address range, @@ -2293,29 +2303,29 @@ static uint8_t da2_mmio_read(uint32_t addr, void* p) return da2->mmio.font[addr]; break; default: - return DA2_INVALIDACCESS8;//invalid memory access + return DA2_INVALIDACCESS8;/* invalid memory access */ break; } } - else if (!(da2->ioctl[LS_MODE] & 1))//8 or 256 color mode + else if (!(da2->ioctl[LS_MODE] & 1))/* 8 or 256 color mode */ { cycles -= video_timing_read_b; for (int i = 0; i < 8; i++) - da2->gdcla[i] = da2->vram[(addr << 3) | i];//read in byte + da2->gdcla[i] = da2->vram[(addr << 3) | i];/* read in byte */ //da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); - if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 + if (da2->gdcreg[LG_MODE] & 0x08) {/* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint8_t ret = 0; for (int i = 0; i < 8; i++) { - if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))/* color don't care register */ ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xff : 0); } return ~ret; } else return da2->gdcla[da2->readplane]; } - else //text mode 3 + else /* text mode 3 */ { cycles -= video_timing_read_b; return da2->vram[addr]; @@ -2328,12 +2338,12 @@ static uint16_t da2_mmio_readw(uint32_t addr, void* p) if (da2->ioctl[LS_MMIO] & 0x10) { return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); } - else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + else if (!(da2->ioctl[LS_MODE] & 1))/* 8 color or 256 color mode */ { cycles -= video_timing_read_w; addr &= DA2_MASK_MMIO; for (int i = 0; i < 8; i++) - da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);//read vram into latch + da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);/* read vram into latch */ #ifdef ENABLE_DA2_DEBUGBLT ////debug @@ -2352,12 +2362,12 @@ static uint16_t da2_mmio_readw(uint32_t addr, void* p) //da2->mmrdbg_vidaddr = addr; #endif - if (da2->gdcreg[LG_MODE] & 0x08) {//compare data across planes if the read mode bit (3EB 05, bit 3) is 1 + if (da2->gdcreg[LG_MODE] & 0x08) {/* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint16_t ret = 0; for (int i = 0; i < 8; i++) { - if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))//color don't care register + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))/* color don't care register */ ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xffff : 0); } return ~ret; @@ -2382,9 +2392,9 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) if (da2->ioctl[LS_MMIO] & 0x10) { //if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI); - //Gaiji RAM + /* Gaiji RAM */ if (da2->fctl[LF_MMIO_SEL] == 0x80) - addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17);//xxxy yyyy yyyy yyyy yyyy + addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17);/* xxxy yyyy yyyy yyyy yyyy */ else { uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; @@ -2393,16 +2403,16 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) addr += index * 0x40; } switch (da2->fctl[LF_MMIO_MODE]) { - case 0xb0://Gaiji RAM 1011 0000 - addr &= DA2_MASK_GAIJIRAM;//safety access + case 0xb0:/* Gaiji RAM 1011 0000 */ + addr &= DA2_MASK_GAIJIRAM;/* safety access */ da2->mmio.ram[addr] = val; break; - case 0x10://Font ROM 0001 0000 - //Read-Only + case 0x10:/* Font ROM 0001 0000 */ + /* Read-Only */ break; case 0x00: //da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - //addr &= 0x7f;//OS/2 write addr 1cf80-1cfc3, val xx + //addr &= 0x7f;/* OS/2 write addr 1cf80-1cfc3, val xx */ //if (addr >= DA2_BLT_MEMSIZE) //{ // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); @@ -2419,12 +2429,11 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) break; } } - else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + else if (!(da2->ioctl[LS_MODE] & 1))/* 8 color or 256 color mode */ { uint8_t wm = da2->writemask; //da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); #ifdef ENABLE_DA2_DEBUGBLT - //debug //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) //{ if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) @@ -2449,7 +2458,7 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) addr <<= 3; for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch + da2->gdcsrc[i] = da2->gdcla[i];/* use latch */ //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); @@ -2485,11 +2494,11 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) else da2->gdcinput[i] = val; for (int i = 0; i < 8; i++) - da2->debug_vramold[i] = da2->vram[addr | i];//use latch + da2->debug_vramold[i] = da2->vram[addr | i];/* use latch */ da2_gdcropB(addr, da2); //for (int i = 0; i < 8; i++) // da2_log("\tsrc %02x in %02x bitm %02x mod %x rop %x: %02x -> %02x\n", da2->gdcsrc[i], da2->gdcinput[i], da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch - //// da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); + ////da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); } break; case 1: @@ -2519,7 +2528,7 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) } //da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); } - else// mode 3h text + else/* mode 3h text */ { cycles -= video_timing_write_b; da2->vram[addr] = val; @@ -2538,7 +2547,6 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) bitmask <<= 8; bitmask |= (uint16_t)da2->gdcreg[LG_BIT_MASK_LOW]; #ifdef ENABLE_DA2_DEBUGBLT - //debug //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) //{ if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) @@ -2567,7 +2575,7 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) addr <<= 3; for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];//use latch + da2->gdcsrc[i] = da2->gdcla[i];/* use latch */ if (!(da2->gdcreg[LG_COMMAND] & 0x08)) { @@ -2608,7 +2616,7 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; else da2->gdcinput[i] = val; da2_gdcropW(addr, bitmask, da2); - // da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); + //da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); } break; case 1: @@ -2653,14 +2661,14 @@ static void da2_mmio_writew(uint32_t addr, uint16_t val, void* p) da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); } - else if (!(da2->ioctl[LS_MODE] & 1))//8 color or 256 color mode + else if (!(da2->ioctl[LS_MODE] & 1))/* 8 color or 256 color mode */ { addr &= DA2_MASK_MMIO; //return; //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_gc_writeW(addr, val, da2); } - else {//mode 3h text + else {/* mode 3h text */ //if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_write(addr, val & 0xff, da2); @@ -2739,7 +2747,7 @@ void da2_poll(void* priv) if (!da2->linepos) { timer_advance_u64(&da2->timer, da2->dispofftime); - // if (output) printf("Display off %f\n",vidtime); + //if (output) printf("Display off %f\n",vidtime); da2->cgastat |= 1; da2->linepos = 1; @@ -2767,21 +2775,21 @@ void da2_poll(void* priv) // da2->displine++; if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) { - //da2_log("Vsync off at line %i\n",displine); + //da2_log("Vsync off at line %i\n",displine); da2->cgastat &= ~8; } da2->vslines++; if (da2->displine > 1200) da2->displine = 0; - // da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], - // displine, vc, ma); + //da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], + //displine, vc, ma); } else { - // da2_log("VC %i ma %05X\n", da2->vc, da2->ma); + //da2_log("VC %i ma %05X\n", da2->vc, da2->ma); timer_advance_u64(&da2->timer, da2->dispontime); - // if (output) printf("Display on %f\n",vidtime); + //if (output) printf("Display on %f\n",vidtime); if (da2->dispon) da2->cgastat &= ~1; da2->hdisp_on = 0; @@ -2796,7 +2804,7 @@ void da2_poll(void* priv) da2->linecountff = 0; da2->sc = 0; - da2->maback += (da2->rowoffset << 1);// color = 0x50(80), mono = 0x40(64) + da2->maback += (da2->rowoffset << 1);/* color = 0x50(80), mono = 0x40(64) */ if (da2->interlace) da2->maback += (da2->rowoffset << 1); da2->maback &= da2->vram_display_mask; @@ -2817,9 +2825,9 @@ void da2_poll(void* priv) { da2->dispon = 0; //if (da2->crtc[10] & 0x20) da2->cursoron = 0; - //else da2->cursoron = da2->blink & 16; - if (da2->ioctl[LS_MODE] & 1) {//in text mode - if (da2->attrc[LV_CURSOR_CONTROL] & 0x01)//cursor blinking + //else da2->cursoron = da2->blink & 16; + if (da2->ioctl[LS_MODE] & 1) {/* in text mode */ + if (da2->attrc[LV_CURSOR_CONTROL] & 0x01)/* cursor blinking */ { da2->cursoron = (da2->blink | 1) & da2->blinkconf; } @@ -2827,7 +2835,7 @@ void da2_poll(void* priv) { da2->cursoron = 0; } - if (!(da2->blink & (0x10 - 1)))//force redrawing for cursor and blink attribute + if (!(da2->blink & (0x10 - 1)))/* force redrawing for cursor and blink attribute */ da2->fullchange = 2; } da2->blink++; @@ -2837,7 +2845,7 @@ void da2_poll(void* priv) if (da2->changedvram[x]) da2->changedvram[x]--; } - // memset(changedvram,0,2048); del + //memset(changedvram,0,2048); del if (da2->fullchange) { da2->fullchange--; @@ -2846,7 +2854,7 @@ void da2_poll(void* priv) if (da2->vc == da2->vsyncstart) { int wx, wy; - // da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); + //da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); da2->dispon = 0; da2->cgastat |= 8; x = da2->hdisp; @@ -2881,14 +2889,12 @@ void da2_poll(void* priv) da2->maback <<= 1; da2->ca <<= 1; - // da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); + //da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); } if (da2->vc == da2->vtotal) { - // da2_log("VC vtotal\n"); - - - // printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); + //da2_log("VC vtotal\n"); + //printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); da2->vc = 0; da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; da2->dispon = 1; @@ -2898,9 +2904,9 @@ void da2_poll(void* priv) if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) da2->con = 1; } - // printf("2 %i\n",da2_vsyncstart); + //printf("2 %i\n",da2_vsyncstart); //da2_log("da2_poll %i %i %i %i %i %i %i\n", ins, da2->dispofftime, da2->dispontime, da2->vidtime, cyc_total, da2->linepos, da2->vc); - //da2_log("r"); + //da2_log("r"); } static void da2_loadfont(char* fname, void* p) { @@ -2916,10 +2922,10 @@ static void da2_loadfont(char* fname, void* p) { return; } fseek(mfile, 0, SEEK_END); - fsize = ftell(mfile);//get filesize + fsize = ftell(mfile); /* get filesize */ fseek(mfile, 0, SEEK_SET); if (fsize > DA2_FONTROM_SIZE) { - fsize = DA2_FONTROM_SIZE;//truncate read data + fsize = DA2_FONTROM_SIZE; /* truncate read data */ //da2_log("MSG: The binary ROM font is truncated: %s\n", fname); //fclose(mfile); //return 1; @@ -2991,8 +2997,6 @@ da2_reset(void* priv) static void *da2_init() { - //Todo: init regs, gaiji memory, video memory, I/O handlers, font ROM - if (svga_get_pri() == NULL) return NULL; svga_t *mb_vga = svga_get_pri(); @@ -3008,7 +3012,7 @@ static void *da2_init() da2->vram_mask = memsize - 1; da2->cram = malloc(0x1000); da2->vram_display_mask = DA2_MASK_CRAM; - da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);//XX000h + da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12); /* XX000h */ da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ da2->mmio.charset = device_get_config_int("charset"); From 33b149e521d12da64e27580af1900f3f16ff563c Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 18:53:44 +0900 Subject: [PATCH 48/82] changed debug message output in keyboard.c --- src/device/keyboard.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index 3fa7760c5..de97592bf 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -190,7 +190,7 @@ key_process(uint16_t scan, int down) oldkey[scan] = down; - pclog("keyboard : %04X,%d in process\n", scan, down); + kbc_at_log("Key %04X,%d in process\n", scan, down); c = 0; /* According to Japanese DOS K3.3 manual (N:SC18-2194-1), @@ -206,7 +206,7 @@ key_process(uint16_t scan, int down) if (scan != 0x1d && scan != 0x2a && scan != 0x138) { key5576mode = 0; - pclog("keyboard : 5576-001 key emulation disabled.\n"); + kbc_at_log("5576-001 key emulation disabled.\n"); } } while (scconv55_8a[i].sc != 0) @@ -251,7 +251,7 @@ key_process(uint16_t scan, int down) if (keyboard_mode == 0x8a && down && ((keyboard_get_shift() & 0x43) == 0x43)) { key5576mode = 1; - pclog("keyboard : 5576-001 key emulation enabled.\n"); + kbc_at_log("5576-001 key emulation enabled.\n"); } } @@ -348,7 +348,7 @@ keyboard_input(int down, uint16_t scan) } } - /* pclog("Received scan code: %03X (%s)\n", scan & 0x1ff, down ? "down" : "up"); */ + /* kbc_at_log("Received scan code: %03X (%s)\n", scan & 0x1ff, down ? "down" : "up"); */ recv_key_ui[scan & 0x1ff] = down; if (mouse_capture || !kbd_req_capture || video_fullscreen) { From 59c3bb794f6acf9f02e5eaff786b8ca4d7b29835 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 19:03:42 +0900 Subject: [PATCH 49/82] revert wrapping changed in recent edits --- src/floppy/fdc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 7f025df2d..a8d2e6520 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -1284,8 +1284,7 @@ fdc_read(uint16_t addr, void *priv) ret |= 0x40; if (fdc->fintr || fdc->reset_stat) /* INTR */ ret |= 0x80; - } - else + } else ret = 0xff; break; case 1: /* STB */ @@ -1360,8 +1359,7 @@ fdc_read(uint16_t addr, void *priv) else ret = 0x00; /* PS/55 POST throws an error and halt if ret = 1 or 2, somehow. */ - } - else if (!fdc->enh_mode) + } else if (!fdc->enh_mode) ret = 0x20; else ret = fdc->rwc[drive] << 4; From 6c5e8897de7a5a0899c9e3230979a1fda8741750 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 19:49:03 +0900 Subject: [PATCH 50/82] update comments --- src/video/vid_ps55da2.c | 6 +++--- src/video/vid_svga.c | 13 ++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 5098fa64d..c7c989c5e 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1562,12 +1562,12 @@ The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh. 16000-17FFFh (B6000-B7FFFh) : Codepage 850 characters (13 x 30) 18000-1A3FFh (B8000-BA3FFh) : CAD control icons and box drawing characters (32 x 32) - Some models have the signature 80h, 01h placed at Bank 0:1AFFEh. (it disables hardware text drawing in OS/2 J1.3) + Some models have the signature 80h, 01h placed at Bank 0:1AFFEh. It disables Bitblt text drawing in OS/2 J1.3. [Font ROM Map (DA3, Traditional Chinese)] Bank 0 - 11 : Valid Font ROM data - Bank 12 : Alias of bank 11 (At least, DOS T5.0 uses this on purpose.) - Bank 13 : All addresses return 0xFF + Bank 12 : Alias of bank 11 (At least, DOS T5.0 uses this on purpose to obtain the SBCS font.) + Bank 13 : Filled by 0xFFh [Gaiji RAM Map (DA2)] Bank 0 00000-1FFFFh placed between A0000h-BFFFFh diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 5d0db103b..db378b754 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -502,20 +502,19 @@ svga_in(uint16_t addr, void *priv) ret = svga->attrregs[svga->attraddr]; break; case 0x3c2: - if (svga->cable_connected) - { + if (svga->cable_connected) { if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) ret = 0; else ret = 0x10; - } - else - { + /* Monitor is not connected to the planar VGA if the PS/55 Display Adapter is installed. */ + } else { /* The IBM PS/55 Display Adapter has own Monitor Type Detection bit in the different I/O port (I/O 3E0h, 3E1h). - When the monitor cable is connected to the Display Adapter, this port returns the value as 'no cable connection'. + When the monitor cable is connected to the Display Adapter, the port 3C2h returns the value as 'no cable connection'. The POST of PS/55 has an extra code that tries detecting the monitor on the planar VGA. - If it fails, then the POST reads the NVRAM set by the reference diskette, and updates the BIOS Data Area (Mem 487h, 489h). + If it fails, then the POST reads the NVRAM set by the reference diskette, and writes the BIOS Data Area (Mem 487h, 489h). + MONCHK.EXE in the reference diskette uses both I/O ports to determine the monitor type, and writes the BDA. */ if (svga->vgapal[0].r >= 10 || svga->vgapal[0].g >= 10 || svga->vgapal[0].b >= 10) ret = 0; From bbc237866bff2458fdfae2bcd2da16902fb14728 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 23:14:07 +0900 Subject: [PATCH 51/82] changed palette initialization method --- src/video/vid_ps55da2.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index c7c989c5e..b4a85bd74 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -2987,11 +2987,11 @@ da2_reset(void* priv) da2->attr_palette_enable = 0; /* disable attribute generator */ /* Set default color palette (Windows 3.1 display driver won't reset palette) */ - da2_out(0x3c8, 0, da2); for (int i = 0; i < 256; i++) { - da2_out(0x3c9, ps55_palette_color[i & 0x3F][0], da2); - da2_out(0x3c9, ps55_palette_color[i & 0x3F][1], da2); - da2_out(0x3c9, ps55_palette_color[i & 0x3F][2], da2); + da2->vgapal[i].r = ps55_palette_color[i & 0x3F][0]; + da2->vgapal[i].g = ps55_palette_color[i & 0x3F][1]; + da2->vgapal[i].b = ps55_palette_color[i & 0x3F][2]; + da2->pallook[i] = makecol32((da2->vgapal[i].r & 0x3f) * 4, (da2->vgapal[i].g & 0x3f) * 4, (da2->vgapal[i].b & 0x3f) * 4); } } @@ -3147,14 +3147,13 @@ void da2_speed_changed(void *p) { da2_t* da2 = (da2_t*)p; da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); - da2_recalctimings(da2); + da2_recalctimings(da2); } void da2_force_redraw(void *p) { da2_t* da2 = (da2_t*)p; - - da2->fullchange = changeframecount; + da2->fullchange = changeframecount; } static const device_config_t da2_configuration[] = { From 5f831603e930bf2e462f72567a7d3aaf44c0fba4 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 23:15:10 +0900 Subject: [PATCH 52/82] fixed cache memory encoding for 5550-V --- src/machine/m_ps2_mca.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index b948c984c..62a5e41cd 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -145,7 +145,7 @@ static struct ps2_t { static uint8_t ps2_cache[65536]; static int ps2_cache_valid[65536 / 8]; static void mem_encoding_update(void); - +#define ENABLE_PS2_MCA_LOG 1 #ifdef ENABLE_PS2_MCA_LOG int ps2_mca_do_log = ENABLE_PS2_MCA_LOG; @@ -452,7 +452,7 @@ ps55_model_50v_read(uint16_t port) } return val; case 0x104: - return ps2.option[2]; + return ps2.option[2] & 0xf3; case 0x105: return ps2.option[3]; case 0x106: @@ -1472,10 +1472,12 @@ mem_encoding_write_cached_ps55(uint16_t addr, uint8_t val, UNUSED(void *priv)) mem_mapping_disable(&ram_low_mapping); mem_mapping_enable(&ps2.cache_mapping); flushmmucache(); + ps2_mca_log("mem_encoding_write: low ram mapping disabled\n"); } else { mem_mapping_disable(&ps2.cache_mapping); mem_mapping_enable(&ram_low_mapping); flushmmucache(); + ps2_mca_log("mem_encoding_write: low ram mapping enabled\n"); } if (ps2.option[2] & 1) /* reset memstate for E0000 - E0FFFh hole */ { @@ -1906,7 +1908,7 @@ ps55_mca_board_model_50v_init() device_add(&ps2_nvr_device); - io_sethandler(0x00e0, 0x0002, mem_encoding_read_cached, NULL, NULL, mem_encoding_write_cached_ps55, NULL, NULL, NULL); + io_sethandler(0x00e0, 0x0003, mem_encoding_read_cached, NULL, NULL, mem_encoding_write_cached_ps55, NULL, NULL, NULL); ps2.mem_regs[1] = 2; ps2.option[2] &= 0xf2; /* Bit 3-2: -Cache IDs, Bit 1: Reserved @@ -1926,6 +1928,20 @@ ps55_mca_board_model_50v_init() NULL); mem_mapping_disable(&ps2.split_mapping); + mem_mapping_add(&ps2.cache_mapping, + 0, + 64 * 1024, + ps2_read_cache_ram, + ps2_read_cache_ramw, + ps2_read_cache_raml, + ps2_write_cache_ram, + NULL, + NULL, + ps2_cache, + MEM_MAPPING_INTERNAL, + NULL); + mem_mapping_disable(&ps2.cache_mapping); + if (mem_size > 8192) { /* Only 8 MB supported on planar, create a memory expansion card for the rest */ ps2_mca_mem_fffc_init(8); From 0a7c3294059aa58a3286a4a4e175ce375907a02c Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 15 Feb 2025 23:25:57 +0900 Subject: [PATCH 53/82] cleanup --- src/machine/m_ps2_mca.c | 333 ++++++++++++++++++++-------------------- 1 file changed, 163 insertions(+), 170 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 62a5e41cd..e89d88f91 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -145,7 +145,7 @@ static struct ps2_t { static uint8_t ps2_cache[65536]; static int ps2_cache_valid[65536 / 8]; static void mem_encoding_update(void); -#define ENABLE_PS2_MCA_LOG 1 + #ifdef ENABLE_PS2_MCA_LOG int ps2_mca_do_log = ENABLE_PS2_MCA_LOG; @@ -367,53 +367,59 @@ static uint8_t ps55_model_50t_read(uint16_t port) { ps2_mca_log(" Read SysBrd %04X xx %04X:%04X\n", port, cs >> 4, cpu_state.pc); - switch (port) - { - case 0x100: - return ps2.planar_id & 0xff; - case 0x101: - return ps2.planar_id >> 8; - case 0x102: - return ps2.option[0]; - case 0x103: - uint8_t val = 0xff; - /* - I/O 103h - Bit 7-4: Memory Card ID (Connector 1 or 3) - Bit 3-0: Memory Card ID (Connector 2) + switch (port) { + case 0x100: + return ps2.planar_id & 0xff; + case 0x101: + return ps2.planar_id >> 8; + case 0x102: + return ps2.option[0]; + case 0x103: + uint8_t val = 0xff; + /* + I/O 103h - Bit 7-4: Memory Card ID (Connector 1 or 3) + Bit 3-0: Memory Card ID (Connector 2) - Memory Card ID: 7h = 2 MB Memory Card 2 or 3 Installed - 5h = 4 MB Memory Card 2 Installed - */ - switch (mem_size / 1024) - { - case 2: - if (ps2.option[1] & 0x04) val = 0xff; - else val = 0x7f; - break; - case 4: - if (ps2.option[1] & 0x04) val = 0xff; - else val = 0x77; - break; - case 6: - if (ps2.option[1] & 0x04) val = 0x7f; - else val = 0x77; - break; - case 8: - default: - if (ps2.option[1] & 0x04) val = 0x5f; - else val = 0x77; - break; - } - ps2_mca_log(" Read MCA %04X %02X %04X:%04X mem_size = %d, ps2option1 = %2X\n", port, val, cs >> 4, cpu_state.pc, mem_size, ps2.option[1]); - return val; - case 0x104: - return ps2.option[2]; - case 0x105: - return ps2.option[3]; - case 0x106: - return ps2.subaddr_lo; - case 0x107: - return ps2.subaddr_hi; + Memory Card ID: 7h = 2 MB Memory Card 2 or 3 Installed + 5h = 4 MB Memory Card 2 Installed + */ + switch (mem_size / 1024) { + case 2: + if (ps2.option[1] & 0x04) + val = 0xff; + else + val = 0x7f; + break; + case 4: + if (ps2.option[1] & 0x04) + val = 0xff; + else + val = 0x77; + break; + case 6: + if (ps2.option[1] & 0x04) + val = 0x7f; + else + val = 0x77; + break; + case 8: + default: + if (ps2.option[1] & 0x04) + val = 0x5f; + else + val = 0x77; + break; + } + ps2_mca_log(" Read MCA %04X %02X %04X:%04X mem_size = %d, ps2option1 = %2X\n", port, val, cs >> 4, cpu_state.pc, mem_size, ps2.option[1]); + return val; + case 0x104: + return ps2.option[2]; + case 0x105: + return ps2.option[3]; + case 0x106: + return ps2.subaddr_lo; + case 0x107: + return ps2.subaddr_hi; } return 0xff; } @@ -421,44 +427,47 @@ ps55_model_50t_read(uint16_t port) static uint8_t ps55_model_50v_read(uint16_t port) { - switch (port) - { - case 0x100: - return ps2.planar_id & 0xff; - case 0x101: - return ps2.planar_id >> 8; - case 0x102: - return ps2.option[0]; - case 0x103: - uint8_t val = 0xff; - /* - I/O 103h - Bit 7-4: Reserved - Bit 3-0: Memory Card ID (Connector 3 or 1) + switch (port) { + case 0x100: + return ps2.planar_id & 0xff; + case 0x101: + return ps2.planar_id >> 8; + case 0x102: + return ps2.option[0]; + case 0x103: + uint8_t val = 0xff; + /* + I/O 103h - Bit 7-4: Reserved + Bit 3-0: Memory Card ID (Connector 3 or 1) - Memory Card ID: 8h = 4 MB Memory Card IV Installed - Fh = No Card Installed - */ - switch (mem_size / 1024) - { - case 4: - if (ps2.option[1] & 0x04) val = 0xff; - else val = 0xf8; - break; - case 8: - default: - if (ps2.option[1] & 0x04) val = 0xf8; - else val = 0xf8; - break; - } - return val; - case 0x104: - return ps2.option[2] & 0xf3; - case 0x105: - return ps2.option[3]; - case 0x106: - return ps2.subaddr_lo; - case 0x107: - return ps2.subaddr_hi; + Memory Card ID: 8h = 4 MB Memory Card IV Installed + Fh = No Card Installed + */ + switch (mem_size / 1024) { + case 4: + if (ps2.option[1] & 0x04) + val = 0xff; + else + val = 0xf8; + break; + case 8: + default: + if (ps2.option[1] & 0x04) + val = 0xf8; + else + val = 0xf8; + break; + } + return val; + case 0x104: + /* Reading cache ID (bit 3-2) always returns zero */ + return ps2.option[2] & 0xf3; + case 0x105: + return ps2.option[3]; + case 0x106: + return ps2.subaddr_lo; + case 0x107: + return ps2.subaddr_hi; } return 0xff; } @@ -763,71 +772,66 @@ static void ps55_model_50tv_write(uint16_t port, uint8_t val) { ps2_mca_log(" Write SysBrd %04X %02X %04X:%04X\n", port, val, cs >> 4, cpu_state.pc); - switch (port) - { - case 0x102: - lpt1_remove(); - serial_remove(ps2.uart); - if (val & 0x04) - { - if (val & 0x08) - serial_setup(ps2.uart, COM1_ADDR, COM1_IRQ); - else - serial_setup(ps2.uart, COM2_ADDR, COM2_IRQ); - } - if (val & 0x10) - { - switch ((val >> 5) & 3) - { - case 0: - lpt1_setup(LPT_MDA_ADDR); - break; - case 1: - lpt1_setup(LPT1_ADDR); - break; - case 2: - lpt1_setup(LPT2_ADDR); - break; - default: - break; + switch (port) { + case 0x102: + lpt1_remove(); + serial_remove(ps2.uart); + if (val & 0x04) { + if (val & 0x08) + serial_setup(ps2.uart, COM1_ADDR, COM1_IRQ); + else + serial_setup(ps2.uart, COM2_ADDR, COM2_IRQ); } - } - ps2.option[0] = val; - break; - case 0x103: - ps2.option[1] = val; - break; - case 0x104: - if ((ps2.option[2] ^ val) & 1) { - mem_encoding_update(); - if (val & 1)/* Disable E0000 - E0FFF(Make 2 KB hole for Display Adapter) */ - { - ps2_mca_log("ROM E0000-E0FFF is disabled.\n"); - //mem_mapping_set_addr(&bios_mapping 0xe1000, 0x1f000); - mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - //mem_mapping_disable(&bios_mapping[0]); + if (val & 0x10) { + switch ((val >> 5) & 3) { + case 0: + lpt1_setup(LPT_MDA_ADDR); + break; + case 1: + lpt1_setup(LPT1_ADDR); + break; + case 2: + lpt1_setup(LPT2_ADDR); + break; + default: + break; + } } - else/* Enable E0000 - E0FFF for BIOS */ - { - ps2_mca_log("ROM E0000-E0FFF is enabled.\n"); - //mem_mapping_set_addr(&bios_mapping 0xe0000, 0x20000); - //mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED); - //mem_mapping_enable(&bios_mapping[0]); + ps2.option[0] = val; + break; + case 0x103: + ps2.option[1] = val; + break; + case 0x104: + if ((ps2.option[2] ^ val) & 1) { + mem_encoding_update(); + if (val & 1) { + /* Disable E0000 - E0FFF (Make 2 KB hole for Display Adapter) */ + ps2_mca_log("ROM E0000-E0FFF is disabled.\n"); + // mem_mapping_set_addr(&bios_mapping 0xe1000, 0x1f000); + mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + // mem_mapping_disable(&bios_mapping[0]); + } else { + /* Enable E0000 - E0FFF for BIOS */ + ps2_mca_log("ROM E0000-E0FFF is enabled.\n"); + // mem_mapping_set_addr(&bios_mapping 0xe0000, 0x20000); + // mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED); + // mem_mapping_enable(&bios_mapping[0]); + } } - } - ps2.option[2] = val; - break; - case 0x105: - ps2.option[3] = val; - break; - case 0x106: - ps2.subaddr_lo = val; - break; - case 0x107: - ps2.subaddr_hi = val; - break; - default: - break; + ps2.option[2] = val; + break; + case 0x105: + ps2.option[3] = val; + break; + case 0x106: + ps2.subaddr_lo = val; + break; + case 0x107: + ps2.subaddr_hi = val; + break; + default: + break; } } @@ -1339,20 +1343,19 @@ static void mem_encoding_write_ps55(uint16_t addr, uint8_t val, void* p) { //ps2_mca_log(" Write Memory Encoding %04X %02X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - switch (addr) - { - case 0xe0: - ps2.mem_regs[0] = val; - break; - case 0xe1: - ps2.mem_regs[1] = val; - break; - default: - break; + switch (addr) { + case 0xe0: + ps2.mem_regs[0] = val; + break; + case 0xe1: + ps2.mem_regs[1] = val; + break; + default: + break; } mem_encoding_update(); - if (ps2.option[2] & 1) /* reset memstate for E0000 - E0FFFh hole */ - { + if (ps2.option[2] & 1) { + /* reset memstate for E0000 - E0FFFh hole */ mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); } } @@ -1479,8 +1482,8 @@ mem_encoding_write_cached_ps55(uint16_t addr, uint8_t val, UNUSED(void *priv)) flushmmucache(); ps2_mca_log("mem_encoding_write: low ram mapping enabled\n"); } - if (ps2.option[2] & 1) /* reset memstate for E0000 - E0FFFh hole */ - { + if (ps2.option[2] & 1) { + /* reset memstate for E0000 - E0FFFh hole */ mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); } } @@ -1845,7 +1848,6 @@ ps55_mca_board_model_50t_init() { ps2_mca_board_common_init(); - //mem_remap_top(256); ps2.split_addr = mem_size * 1024; /* The slot 5 is reserved for the Integrated Fixed Disk II (an internal ESDI hard drive). */ mca_init(5); @@ -1861,14 +1863,6 @@ ps55_mca_board_model_50t_init() ps2.mem_regs[1] = 2; ps2.option[2] &= 0xfe; /* Bit 0: Disable E0000-E0FFFh (4 KB) */ - //resize bios_mapping 0,1 - //mem_mapping_set_addr(&bios_mapping[0], 0xe0000, 0x1000); - //mem_mapping_set_exec(&bios_mapping[0], rom + (0x20000 & biosmask)); - //mem_mapping_set_addr(&bios_mapping[1], 0xe1000, 0x7000); - //mem_mapping_set_exec(&bios_mapping[1], rom + (0x21000 & biosmask)); - //mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x20000 & biosmask), MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM, 0); - //mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x23000 & biosmask), MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM, 0); - mem_mapping_add(&ps2.split_mapping, (mem_size + 256) * 1024, 256 * 1024, @@ -1897,7 +1891,6 @@ ps55_mca_board_model_50v_init() { ps2_mca_board_common_init(); - //mem_remap_top(256); ps2.split_addr = mem_size * 1024; /* The slot 5 is reserved for the Integrated Fixed Disk II (an internal ESDI hard drive). */ mca_init(5); From 5dfbef2374a11c77cf77407eb109f816ee6944a6 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sun, 16 Feb 2025 11:11:44 +0900 Subject: [PATCH 54/82] fixed PS/55 5550-V hangs in warm boot * Fixed PS/55 5550-V hangs in warm boot because it doesn't reset E0000-E0FFFh hole (for video RAM of DA) * Merge code that enable/disable E0000-E0FFFh hole --- src/machine/m_ps2_mca.c | 119 ++++++++-------------------------------- 1 file changed, 24 insertions(+), 95 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index e89d88f91..1edff2991 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -107,6 +107,7 @@ static struct ps2_t { serial_t *uart; vga_t* mb_vga; + int has_e0000_hole; } ps2; /*The model 70 type 3/4 BIOS performs cache testing. Since 86Box doesn't have any @@ -145,7 +146,7 @@ static struct ps2_t { static uint8_t ps2_cache[65536]; static int ps2_cache_valid[65536 / 8]; static void mem_encoding_update(void); - +// #define ENABLE_PS2_MCA_LOG 1 #ifdef ENABLE_PS2_MCA_LOG int ps2_mca_do_log = ENABLE_PS2_MCA_LOG; @@ -804,20 +805,9 @@ ps55_model_50tv_write(uint16_t port, uint8_t val) break; case 0x104: if ((ps2.option[2] ^ val) & 1) { + /* Disable/Enable E0000 - E0FFF (Make 2 KB hole for Display Adapter) */ + ps2.option[2] = val; mem_encoding_update(); - if (val & 1) { - /* Disable E0000 - E0FFF (Make 2 KB hole for Display Adapter) */ - ps2_mca_log("ROM E0000-E0FFF is disabled.\n"); - // mem_mapping_set_addr(&bios_mapping 0xe1000, 0x1f000); - mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - // mem_mapping_disable(&bios_mapping[0]); - } else { - /* Enable E0000 - E0FFF for BIOS */ - ps2_mca_log("ROM E0000-E0FFF is enabled.\n"); - // mem_mapping_set_addr(&bios_mapping 0xe0000, 0x20000); - // mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED); - // mem_mapping_enable(&bios_mapping[0]); - } } ps2.option[2] = val; break; @@ -952,8 +942,15 @@ ps2_mca_write(uint16_t port, uint8_t val, UNUSED(void *priv)) ps2.setup = val; break; case 0x96: - if ((val & 0x80) && !(ps2.adapter_setup & 0x80)) + if ((val & 0x80) && !(ps2.adapter_setup & 0x80)) { mca_reset(); + if (ps2.has_e0000_hole) { + /* Reset memstate for E0000 - E0FFFh hole (for PS/55 5550-V) + 5550-T does this in POST, but 5550-V doesn't. */ + ps2.option[2] &= 0xFE; + mem_encoding_update(); + } + } ps2.adapter_setup = val; mca_set_index(val & 7); break; @@ -1306,6 +1303,11 @@ mem_encoding_update(void) ps2_mca_log("PS/2 Model 80-111: Split memory block disabled\n"); } + if (ps2.has_e0000_hole && (ps2.option[2] & 1)) { + /* Set memstate for E0000 - E0FFFh hole (PS/55 only) */ + mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + flushmmucache_nopc(); } @@ -1339,26 +1341,7 @@ mem_encoding_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) } mem_encoding_update(); } -static void -mem_encoding_write_ps55(uint16_t addr, uint8_t val, void* p) -{ - //ps2_mca_log(" Write Memory Encoding %04X %02X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - switch (addr) { - case 0xe0: - ps2.mem_regs[0] = val; - break; - case 0xe1: - ps2.mem_regs[1] = val; - break; - default: - break; - } - mem_encoding_update(); - if (ps2.option[2] & 1) { - /* reset memstate for E0000 - E0FFFh hole */ - mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } -} + static uint8_t mem_encoding_read_cached(uint16_t addr, UNUSED(void *priv)) { @@ -1429,64 +1412,6 @@ mem_encoding_write_cached(uint16_t addr, uint8_t val, UNUSED(void *priv)) } } -static void -mem_encoding_write_cached_ps55(uint16_t addr, uint8_t val, UNUSED(void *priv)) -{ - uint8_t old; - - switch (addr) { - case 0xe0: - ps2.mem_regs[0] = val; - break; - case 0xe1: - ps2.mem_regs[1] = val; - break; - case 0xe2: - old = ps2.mem_regs[2]; - ps2.mem_regs[2] = (ps2.mem_regs[2] & 0x80) | (val & ~0x88); - if (val & 2) { - ps2_mca_log("Clear latch - %i\n", ps2.pending_cache_miss); - if (ps2.pending_cache_miss) - ps2.mem_regs[2] |= 0x80; - else - ps2.mem_regs[2] &= ~0x80; - ps2.pending_cache_miss = 0; - } - - if ((val & 0x21) == 0x20 && (old & 0x21) != 0x20) - ps2.pending_cache_miss = 1; - if ((val & 0x21) == 0x01 && (old & 0x21) != 0x01) - ps2_cache_clean(); -#if 1 - // FIXME: Look into this!!! - if (val & 0x01) - ram_mid_mapping.flags |= MEM_MAPPING_ROM_WS; - else - ram_mid_mapping.flags &= ~MEM_MAPPING_ROM_WS; -#endif - break; - - default: - break; - } - ps2_mca_log("mem_encoding_write: addr=%02x val=%02x %04x:%04x %02x %02x\n", addr, val, CS, cpu_state.pc, ps2.mem_regs[1], ps2.mem_regs[2]); - mem_encoding_update(); - if ((ps2.mem_regs[1] & 0x10) && (ps2.mem_regs[2] & 0x21) == 0x20) { - mem_mapping_disable(&ram_low_mapping); - mem_mapping_enable(&ps2.cache_mapping); - flushmmucache(); - ps2_mca_log("mem_encoding_write: low ram mapping disabled\n"); - } else { - mem_mapping_disable(&ps2.cache_mapping); - mem_mapping_enable(&ram_low_mapping); - flushmmucache(); - ps2_mca_log("mem_encoding_write: low ram mapping enabled\n"); - } - if (ps2.option[2] & 1) { - /* reset memstate for E0000 - E0FFFh hole */ - mem_set_mem_state(0xe0000, 0x1000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } -} static void ps2_mca_board_model_70_type34_init(int is_type4, int slots) { @@ -1675,6 +1600,8 @@ machine_ps2_common_init(const machine_t *model) nmi_mask = 0x80; ps2.uart = device_add_inst(&ns16550_device, 1); + + ps2.has_e0000_hole = 0; } int @@ -1858,10 +1785,11 @@ ps55_mca_board_model_50t_init() device_add(&ps2_nvr_device); - io_sethandler(0x00e0, 0x0002, mem_encoding_read, NULL, NULL, mem_encoding_write_ps55, NULL, NULL, NULL); + io_sethandler(0x00e0, 0x0002, mem_encoding_read, NULL, NULL, mem_encoding_write, NULL, NULL, NULL); ps2.mem_regs[1] = 2; ps2.option[2] &= 0xfe; /* Bit 0: Disable E0000-E0FFFh (4 KB) */ + ps2.has_e0000_hole = 1; mem_mapping_add(&ps2.split_mapping, (mem_size + 256) * 1024, @@ -1901,11 +1829,12 @@ ps55_mca_board_model_50v_init() device_add(&ps2_nvr_device); - io_sethandler(0x00e0, 0x0003, mem_encoding_read_cached, NULL, NULL, mem_encoding_write_cached_ps55, NULL, NULL, NULL); + io_sethandler(0x00e0, 0x0003, mem_encoding_read_cached, NULL, NULL, mem_encoding_write_cached, NULL, NULL, NULL); ps2.mem_regs[1] = 2; ps2.option[2] &= 0xf2; /* Bit 3-2: -Cache IDs, Bit 1: Reserved Bit 0: Disable E0000-E0FFFh (4 KB) */ + ps2.has_e0000_hole = 1; mem_mapping_add(&ps2.split_mapping, (mem_size + 256) * 1024, From 3f3d77310e769ab52d78b7cf63bd8e20cab433ba Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sun, 16 Feb 2025 12:21:16 +0900 Subject: [PATCH 55/82] cleanup format --- src/video/vid_ps55da2.c | 3436 +++++++++++++++++++-------------------- 1 file changed, 1715 insertions(+), 1721 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index b4a85bd74..9ed099f19 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -37,42 +37,42 @@ #include <86box/vid_svga_render.h> #include "cpu.h" -#define DA2_FONTROM_PATH_JPAN "roms/video/da2/94X1320.BIN" -#define DA2_FONTROM_PATH_HANT "roms/video/da2/23F2698.BIN" -#define DA2_FONTROM_SIZE 1536*1024 -#define DA2_FONTROM_BASESBCS 0x98000 -#define DA2_GAIJIRAM_SBCS 0x34000 -#define DA2_GAIJIRAM_SBEX 0x3c000 -#define DA2_INVALIDACCESS8 0xff -#define DA2_MASK_MMIO 0x1ffff -#define DA2_MASK_GRAM 0x1ffff -#define DA2_MASK_CRAM 0xfff -#define DA2_MASK_GAIJIRAM 0x3ffff -#define DA2_PIXELCLOCK 58000000.0 -#define DA2_BLT_MEMSIZE 0x100 -#define DA2_BLT_REGSIZE 0x40 -#define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) -#define DA2_DEBUG_BLTLOG_MAX 256*1024 -#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe -#define DA2_DEBUG_BLT_USEDRESET 0xfefefe +#define DA2_FONTROM_PATH_JPAN "roms/video/da2/94X1320.BIN" +#define DA2_FONTROM_PATH_HANT "roms/video/da2/23F2698.BIN" +#define DA2_FONTROM_SIZE 1536 * 1024 +#define DA2_FONTROM_BASESBCS 0x98000 +#define DA2_GAIJIRAM_SBCS 0x34000 +#define DA2_GAIJIRAM_SBEX 0x3c000 +#define DA2_INVALIDACCESS8 0xff +#define DA2_MASK_MMIO 0x1ffff +#define DA2_MASK_GRAM 0x1ffff +#define DA2_MASK_CRAM 0xfff +#define DA2_MASK_GAIJIRAM 0x3ffff +#define DA2_PIXELCLOCK 58000000.0 +#define DA2_BLT_MEMSIZE 0x100 +#define DA2_BLT_REGSIZE 0x40 +#define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) +#define DA2_DEBUG_BLTLOG_MAX 256 * 1024 +#define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe +#define DA2_DEBUG_BLT_USEDRESET 0xfefefe #define DA2_DCONFIG_CHARSET_JPAN 0 /* for Code page 932 Japanese */ -//#define DA2_DCONFIG_CHARSET_HANG 1 /* for Code page 934 Hangul */ -//#define DA2_DCONFIG_CHARSET_HANS 2 /* for Code page 936 Simplified Chinese */ +// #define DA2_DCONFIG_CHARSET_HANG 1 /* for Code page 934 Hangul */ +// #define DA2_DCONFIG_CHARSET_HANS 2 /* for Code page 936 Simplified Chinese */ /* These ROMs are currently not found. At least, IBM-J released a Korean and PRC version of PS/55 for each market. */ -#define DA2_DCONFIG_CHARSET_HANT 3 /* for Code page 938 Traditional Chinese */ +#define DA2_DCONFIG_CHARSET_HANT 3 /* for Code page 938 Traditional Chinese */ #define DA2_DCONFIG_MONTYPE_COLOR 0x0A -#define DA2_DCONFIG_MONTYPE_8515 0x0B -#define DA2_DCONFIG_MONTYPE_MONO 0x09 +#define DA2_DCONFIG_MONTYPE_8515 0x0B +#define DA2_DCONFIG_MONTYPE_MONO 0x09 -#define DA2_BLT_CIDLE 0 -#define DA2_BLT_CFILLRECT 1 -#define DA2_BLT_CFILLTILE 2 -#define DA2_BLT_CCOPYF 3 -#define DA2_BLT_CCOPYR 4 -#define DA2_BLT_CPUTCHAR 5 -#define DA2_BLT_CDONE 6 -#define DA2_BLT_CLOAD 7 +#define DA2_BLT_CIDLE 0 +#define DA2_BLT_CFILLRECT 1 +#define DA2_BLT_CFILLTILE 2 +#define DA2_BLT_CCOPYF 3 +#define DA2_BLT_CCOPYR 4 +#define DA2_BLT_CPUTCHAR 5 +#define DA2_BLT_CDONE 6 +#define DA2_BLT_CLOAD 7 /* POS ID = 0xeffe : Display Adapter II, III, V */ #define DA2_POSID_H 0xef #define DA2_POSID_L 0xfe @@ -94,7 +94,7 @@ EFD8h * Display Adapter/J [Atlas-SP2] [Japanese DOS and Display Adapter compatibility] - | POS ID | Adapter Name | K3.31 | J4.04 | J5.02 | OS2 J1.3 | Win3 | + | POS ID | Adapter Name | K3.31 | J4.04 | J4.08 | OS2 J1.3 | Win3 | |------------|-----------------------------|:-----:|:-----:|:-----:|:--------:|:----:| | EFFFh | Display Adapter | X | | | ? | | | FFEDh | ? [Atlas EVT] | X | | | ? | | @@ -107,21 +107,21 @@ | EFD8h | Display Adapter /J | | | X | X | X | */ /* IO 3E0/3E1:0Ah Hardware Configuration Value L (imported from OS/2 DDK) */ -#define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ -//#define Mon_ID3 0x10 -#define FontCard 0x08 /* ? */ -#define Page_One 0x06 /* 80000h 110b */ -#define Page_Two 0x05 /* 100000h 101b */ -#define Page_Four 0x03 /* 200000h 011b */ +#define OldLSI 0x20 /* 1 = DA-2, 0 = DA-3 */ +// #define Mon_ID3 0x10 +#define FontCard 0x08 /* ? */ +#define Page_One 0x06 /* 80000h 110b */ +#define Page_Two 0x05 /* 100000h 101b */ +#define Page_Four 0x03 /* 200000h 011b */ /* Page Number Mask : Memory Size? = (110b and 111b): vram size is 512k (256 color mode unsupported). */ /* IO 3E0/3E1:0Bh Hardware Configuration Value H (imported from OS/2 DDK) */ -#define AddPage 0x08 /* ? */ -//#define Mon_ID2 0x04 -//#define Mon_ID1 0x02 -//#define Mon_ID0 0x01 +#define AddPage 0x08 /* ? */ +// #define Mon_ID2 0x04 +// #define Mon_ID1 0x02 +// #define Mon_ID0 0x01 -/* Monitor ID (imported from OS/2 DDK 1.2) +/* Monitor ID (imported from OS/2 DDK 1.2) #define StarbuckC 0x0A // 1 010b IBM 8514, 9518 color 1040x768 #define StarbuckM 0x09 // 1 001b IBM 8507, 8604 grayscale #define Lark_B 0x02 // 0 010b IBM 9517 color 1040x768 but 4bpp @@ -133,114 +133,114 @@ #define AC_DMAE 0x80 #define AC_FONT_SEL 0x40 #define FONT_BANK 0x3EF -#define LS_INDEX 0x3E0 -#define LS_DATA 0x3E1 +#define LS_INDEX 0x3E0 +#define LS_DATA 0x3E1 #define LS_RESET 0x00 #define LS_MODE 0x02 #define LS_STATUS 0x03 /* added */ #define LS_MMIO 0x08 /* added */ -#define LS_CONFIG1 0x0a -#define LS_CONFIG2 0x0b /* added */ -#define LF_INDEX 0x3e2 -#define LF_DATA 0x3e3 -#define LF_MMIO_SEL 0x08 /* added */ -#define LF_MMIO_ADDR 0x0A /* added */ -#define LF_MMIO_MODE 0x0B /* added */ -#define LC_INDEX 0x3E4 -#define LC_DATA 0x3E5 -#define LC_HORIZONTAL_TOTAL 0x00 -#define LC_H_DISPLAY_ENABLE_END 0x01 -#define LC_START_H_BLANKING 0x02 -#define LC_END_H_BLANKING 0x03 -#define LC_START_HSYNC_PULSE 0x04 -#define LC_END_HSYNC_PULSE 0x05 -#define LC_VERTICAL_TOTALJ 0x06 -#define LC_CRTC_OVERFLOW 0x07 -#define LC_PRESET_ROW_SCANJ 0x08 -#define LC_MAXIMUM_SCAN_LINE 0x09 -#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_ROW_CURSOR_LOC 0x0E -#define LC_CURSOR_LOC_LOWJ 0x0F -#define LC_COLUMN_CURSOR_LOC 0x0F -#define LC_VERTICAL_SYNC_START 0x10 -#define LC_LIGHT_PEN_HIGH 0x10 -#define LC_VERTICAL_SYNC_END 0x11 -#define LC_LIGHT_PEN_LOW 0x11 -#define LC_V_DISPLAY_ENABLE_END 0x12 -#define LC_OFFSET 0x13 -#define LC_UNDERLINE_LOCATION 0x14 -#define LC_START_VERTICAL_BLANK 0x15 -#define LC_END_VERTICAL_BLANK 0x16 -#define LC_LC_MODE_CONTROL 0x17 -#define LC_LINE_COMPAREJ 0x18 -#define LC_START_H_DISPLAY_ENAB 0x19 -#define LC_START_V_DISPLAY_ENAB 0x1A -#define LC_VIEWPORT_COMMAND 0x1B -#define LC_VIEWPORT_SELECT 0x1C -#define LC_VIEWPORT_PRIORITY 0x1D -#define LC_COMMAND 0x1E -#define LC_COMPATIBILITY 0x1F -#define LC_VIEWPORT_NUMBER 0x1F +#define LS_CONFIG1 0x0a +#define LS_CONFIG2 0x0b /* added */ +#define LF_INDEX 0x3e2 +#define LF_DATA 0x3e3 +#define LF_MMIO_SEL 0x08 /* added */ +#define LF_MMIO_ADDR 0x0A /* added */ +#define LF_MMIO_MODE 0x0B /* added */ +#define LC_INDEX 0x3E4 +#define LC_DATA 0x3E5 +#define LC_HORIZONTAL_TOTAL 0x00 +#define LC_H_DISPLAY_ENABLE_END 0x01 +#define LC_START_H_BLANKING 0x02 +#define LC_END_H_BLANKING 0x03 +#define LC_START_HSYNC_PULSE 0x04 +#define LC_END_HSYNC_PULSE 0x05 +#define LC_VERTICAL_TOTALJ 0x06 +#define LC_CRTC_OVERFLOW 0x07 +#define LC_PRESET_ROW_SCANJ 0x08 +#define LC_MAXIMUM_SCAN_LINE 0x09 +#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_ROW_CURSOR_LOC 0x0E +#define LC_CURSOR_LOC_LOWJ 0x0F +#define LC_COLUMN_CURSOR_LOC 0x0F +#define LC_VERTICAL_SYNC_START 0x10 +#define LC_LIGHT_PEN_HIGH 0x10 +#define LC_VERTICAL_SYNC_END 0x11 +#define LC_LIGHT_PEN_LOW 0x11 +#define LC_V_DISPLAY_ENABLE_END 0x12 +#define LC_OFFSET 0x13 +#define LC_UNDERLINE_LOCATION 0x14 +#define LC_START_VERTICAL_BLANK 0x15 +#define LC_END_VERTICAL_BLANK 0x16 +#define LC_LC_MODE_CONTROL 0x17 +#define LC_LINE_COMPAREJ 0x18 +#define LC_START_H_DISPLAY_ENAB 0x19 +#define LC_START_V_DISPLAY_ENAB 0x1A +#define LC_VIEWPORT_COMMAND 0x1B +#define LC_VIEWPORT_SELECT 0x1C +#define LC_VIEWPORT_PRIORITY 0x1D +#define LC_COMMAND 0x1E +#define LC_COMPATIBILITY 0x1F +#define LC_VIEWPORT_NUMBER 0x1F #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 LG_INDEX 0x3EA -#define LG_DATA 0x3EB -#define LG_SET_RESETJ 0x00 -#define LG_ENABLE_SRJ 0x01 -#define LG_COLOR_COMPAREJ 0x02 -#define LG_DATA_ROTATION 0x03 -#define LG_READ_MAP_SELECT 0x04 -#define LG_MODE 0x05 -#define LG_COMPLEMENT 0x06 -#define LG_COLOR_DONT_CARE 0x07 -#define LG_BIT_MASK_LOW 0x08 -#define LG_BIT_MASK_HIGH 0x09 -#define LG_MAP_MASKJ 0x0A -#define LG_COMMAND 0x0B -#define LG_SET_RESET_2 0x10 +#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 LG_INDEX 0x3EA +#define LG_DATA 0x3EB +#define LG_SET_RESETJ 0x00 +#define LG_ENABLE_SRJ 0x01 +#define LG_COLOR_COMPAREJ 0x02 +#define LG_DATA_ROTATION 0x03 +#define LG_READ_MAP_SELECT 0x04 +#define LG_MODE 0x05 +#define LG_COMPLEMENT 0x06 +#define LG_COLOR_DONT_CARE 0x07 +#define LG_BIT_MASK_LOW 0x08 +#define LG_BIT_MASK_HIGH 0x09 +#define LG_MAP_MASKJ 0x0A +#define LG_COMMAND 0x0B +#define LG_SET_RESET_2 0x10 #ifndef RELEASE_BUILD -//#define ENABLE_DA2_LOG 1 +// #define ENABLE_DA2_LOG 1 #endif #ifdef ENABLE_DA2_LOG -#define ENABLE_DA2_DEBUGBLT 1 +# define ENABLE_DA2_DEBUGBLT 1 int da2_do_log = ENABLE_DA2_LOG; static void -da2_log(const char* fmt, ...) +da2_log(const char *fmt, ...) { va_list ap; @@ -254,22 +254,21 @@ da2_log(const char* fmt, ...) # define da2_log(fmt, ...) #endif -typedef struct da2_t -{ - //mem_mapping_t vmapping; +typedef struct da2_t { + // mem_mapping_t vmapping; mem_mapping_t cmapping; - //uint8_t crtcreg; - uint8_t ioctl[16]; - uint8_t fctl[32]; + // uint8_t crtcreg; + uint8_t ioctl[16]; + uint8_t fctl[32]; uint16_t crtc[128]; - uint8_t gdcreg[64]; - uint8_t reg3ee[16]; - int gdcaddr; - uint8_t attrc[0x40]; - int attraddr, attrff; - int attr_palette_enable; - //uint8_t seqregs[64]; + uint8_t gdcreg[64]; + uint8_t reg3ee[16]; + int gdcaddr; + uint8_t attrc[0x40]; + int attraddr, attrff; + int attr_palette_enable; + // uint8_t seqregs[64]; int outflipflop; int inflipflop; int iolatch; @@ -288,8 +287,8 @@ typedef struct da2_t uint32_t debug_vramold[8]; uint8_t dac_mask, dac_status; - int dac_read, dac_write, dac_pos; - int dac_r, dac_g; + int dac_read, dac_write, dac_pos; + int dac_r, dac_g; uint8_t cgastat; @@ -297,37 +296,37 @@ typedef struct da2_t int fb_only; - int fast; - uint8_t colourcompare, colournocare; - int readmode, writemode, readplane; - uint8_t writemask; + int fast; + uint8_t colourcompare, colournocare; + int readmode, writemode, readplane; + uint8_t writemask; uint32_t charseta, charsetb; - uint8_t egapal[16]; + uint8_t egapal[16]; uint32_t pallook[512]; - PALETTE vgapal; + PALETTE vgapal; - int vtotal, dispend, vsyncstart, split, vblankstart; - int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; - int lowres, interlace; - int rowcount; - double clock; + int vtotal, dispend, vsyncstart, split, vblankstart; + int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; + int lowres, interlace; + int rowcount; + double clock; uint32_t ma_latch, ca_adj; - uint64_t dispontime, dispofftime; + uint64_t dispontime, dispofftime; pc_timer_t timer; - uint64_t da2const; + uint64_t da2const; int dispon; int hdisp_on; uint32_t ma, maback, ca; - int vc; - int sc; - int linepos, vslines, linecountff, oddeven; - int con, cursoron, blink, blinkconf; - int scrollcache; - int char_width; + int vc; + int sc; + int linepos, vslines, linecountff, oddeven; + int con, cursoron, blink, blinkconf; + int scrollcache; + int char_width; int firstline, lastline; int firstline_draw, lastline_draw; @@ -336,7 +335,7 @@ typedef struct da2_t /* Attribute Buffer E0000-E0FFFh (4 KB) */ uint8_t *cram; /* (cram size - 1) >> 3 = 0xFFF */ - //uint32_t cram_display_mask; + // uint32_t cram_display_mask; /* APA Buffer A0000-BFFFFh (128 KB) */ uint8_t *vram; /* addr >> 12 = xx000h */ @@ -344,11 +343,11 @@ typedef struct da2_t /* (vram size - 1) >> 3 = 0x1FFFF */ uint32_t vram_display_mask; - //uint32_t write_bank, read_bank; + // uint32_t write_bank, read_bank; int fullchange; - void (*render)(struct da2_t* da2); + void (*render)(struct da2_t *da2); /*If set then another device is driving the monitor output and the SVGA card should not attempt to display anything */ @@ -357,41 +356,41 @@ typedef struct da2_t /* end VGA compatible regs*/ struct { - int enable; + int enable; mem_mapping_t mapping; - uint8_t ram[256 * 1024]; - uint8_t *font; - int charset; + uint8_t ram[256 * 1024]; + uint8_t *font; + int charset; } mmio; struct { - int bitshift_destr; - int raster_op; - uint8_t payload[DA2_BLT_MEMSIZE]; - int32_t reg[DA2_BLT_REGSIZE];//must be signed int - int32_t* debug_reg;//for debug - int debug_reg_ip;//for debug - int payload_addr; + int bitshift_destr; + int raster_op; + uint8_t payload[DA2_BLT_MEMSIZE]; + int32_t reg[DA2_BLT_REGSIZE]; // must be signed int + int32_t *debug_reg; // for debug + int debug_reg_ip; // for debug + int payload_addr; pc_timer_t timer; - int64_t timerspeed; - int exec; - int indata; - int32_t destaddr; - int32_t srcaddr; - int32_t size_x, tile_w; - int32_t size_y; - int16_t destpitch; - int16_t srcpitch; - int32_t fcolor; - int32_t maskl, maskr; - int x, y; + int64_t timerspeed; + int exec; + int indata; + int32_t destaddr; + int32_t srcaddr; + int32_t size_x, tile_w; + int32_t size_y; + int16_t destpitch; + int16_t srcpitch; + int32_t fcolor; + int32_t maskl, maskr; + int x, y; } bitblt; - FILE* mmdbg_fp; - FILE* mmrdbg_fp; + FILE *mmdbg_fp; + FILE *mmrdbg_fp; uint32_t mmdbg_vidaddr; uint32_t mmrdbg_vidaddr; - + uint8_t pos_regs[8]; svga_t *mb_vga; uint8_t monitorid; @@ -399,16 +398,16 @@ typedef struct da2_t int old_pos2; } da2_t; -void da2_recalctimings(da2_t* da2); -static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p); -void da2_bitblt_exec(void* p); -void da2_updatevidselector(da2_t* da2); -void da2_reset_ioctl(da2_t* da2); -static void da2_reset(void* priv); +void da2_recalctimings(da2_t *da2); +static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p); +void da2_bitblt_exec(void *p); +void da2_updatevidselector(da2_t *da2); +void da2_reset_ioctl(da2_t *da2); +static void da2_reset(void *priv); typedef union { uint32_t d; - uint8_t b[4]; + uint8_t b[4]; } DA2_VidSeq32; typedef struct { @@ -416,64 +415,69 @@ typedef struct { } pixel32; /* safety read for internal functions */ -uint32_t DA2_readvram_s(uint32_t addr, da2_t* da2) +uint32_t +DA2_readvram_s(uint32_t addr, da2_t *da2) { - if (addr & ~da2->vram_mask) return -1; + if (addr & ~da2->vram_mask) + return -1; return da2->vram[addr]; } -void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32* srcpx, da2_t* da2) +void +DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *srcpx, da2_t *da2) { uint32_t writepx[8]; - destaddr &= 0xfffffffe;/* align to word address to work bit shift correctly */ - //da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); - da2->changedvram[(da2->vram_display_mask & destaddr) >> 12] = changeframecount; - da2->changedvram[(da2->vram_display_mask & (destaddr+1)) >> 12] = changeframecount; + destaddr &= 0xfffffffe; /* align to word address to work bit shift correctly */ + // da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); + da2->changedvram[(da2->vram_display_mask & destaddr) >> 12] = changeframecount; + da2->changedvram[(da2->vram_display_mask & (destaddr + 1)) >> 12] = changeframecount; destaddr <<= 3; /* read destination data with big endian order */ for (int i = 0; i < 8; i++) writepx[i] = DA2_readvram_s((destaddr + 24) | i, da2) - | (DA2_readvram_s((destaddr + 16) | i, da2) << 8) - | (DA2_readvram_s((destaddr + 8) | i, da2) << 16) - | (DA2_readvram_s((destaddr + 0) | i, da2) << 24); + | (DA2_readvram_s((destaddr + 16) | i, da2) << 8) + | (DA2_readvram_s((destaddr + 8) | i, da2) << 16) + | (DA2_readvram_s((destaddr + 0) | i, da2) << 24); - DA2_VidSeq32 mask32in; mask32in.d = (uint32_t)mask; - DA2_VidSeq32 mask32; mask32.d = 0; + DA2_VidSeq32 mask32in; + mask32in.d = (uint32_t) mask; + DA2_VidSeq32 mask32; + mask32.d = 0; mask32.b[3] = mask32in.b[0]; mask32.b[2] = mask32in.b[1]; mask32.d &= 0xffff0000; - for (int i = 0; i < 8; i++) - { + for (int i = 0; i < 8; i++) { if (da2->bitblt.bitshift_destr > 0) - srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; + srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; switch (da2->bitblt.raster_op) { - case 0x00: /* None */ - writepx[i] &= ~mask32.d; - writepx[i] |= srcpx->p8[i] & mask32.d; - break; - case 0x01: /* AND */ - writepx[i] &= srcpx->p8[i] | ~mask32.d; - break; - case 0x02: /* OR */ - writepx[i] |= srcpx->p8[i] & mask32.d; - break; - case 0x03: /* XOR */ - writepx[i] ^= srcpx->p8[i] & mask32.d; - break; + case 0x00: /* None */ + writepx[i] &= ~mask32.d; + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x01: /* AND */ + writepx[i] &= srcpx->p8[i] | ~mask32.d; + break; + case 0x02: /* OR */ + writepx[i] |= srcpx->p8[i] & mask32.d; + break; + case 0x03: /* XOR */ + writepx[i] ^= srcpx->p8[i] & mask32.d; + break; } } for (int i = 0; i < 8; i++) { - da2->vram[(da2->vram_mask & destaddr) | i] = (writepx[i] >> 24) & 0xff; + da2->vram[(da2->vram_mask & destaddr) | i] = (writepx[i] >> 24) & 0xff; da2->vram[(da2->vram_mask & (destaddr + 8)) | i] = (writepx[i] >> 16) & 0xff; } } -void DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t* da2) +void +DA2_DrawColorWithBitmask(uint32_t destaddr, uint8_t color, uint16_t mask, da2_t *da2) { pixel32 srcpx; /* fill data with input color */ for (int i = 0; i < 8; i++) - srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0;/* read in word */ + srcpx.p8[i] = (color & (1 << i)) ? 0xffffffff : 0; /* read in word */ DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } @@ -487,7 +491,7 @@ Param Desc 09 Mask Right 0A Plane Mask? 0B ROP?(8h or 200h + 0-3h) -0D +0D 20 Exec (1) 21 ? 22 ? @@ -499,20 +503,22 @@ Param Desc 33 Size W 35 Size H */ -void DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) +void +DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2) { pixel32 srcpx; srcaddr &= 0xfffffffe; srcaddr <<= 3; for (int i = 0; i < 8; i++) srcpx.p8[i] = DA2_readvram_s((srcaddr + 24) | i, da2) - | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) - | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) + | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) + | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24); DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } -void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t* da2) +void +DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, da2_t *da2) { pixel32 srcpx; if (srcaddr >= DA2_FONTROM_SIZE) { @@ -520,134 +526,147 @@ void DA2_PutcharWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, return; } for (int i = 0; i < 8; i++) - srcpx.p8[i] = ((uint32_t)da2->mmio.font[srcaddr] << 24) - | ((uint32_t)da2->mmio.font[srcaddr + 1] << 16) - | ((uint32_t)da2->mmio.font[srcaddr + 2] << 8) - | ((uint32_t)da2->mmio.font[srcaddr + 3] << 0); + srcpx.p8[i] = ((uint32_t) da2->mmio.font[srcaddr] << 24) + | ((uint32_t) da2->mmio.font[srcaddr + 1] << 16) + | ((uint32_t) da2->mmio.font[srcaddr + 2] << 8) + | ((uint32_t) da2->mmio.font[srcaddr + 3] << 0); DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } #ifdef ENABLE_DA2_DEBUGBLT -uint8_t pixel1tohex(uint32_t addr, int index, da2_t* da2) { +uint8_t +pixel1tohex(uint32_t addr, int index, da2_t *da2) +{ uint8_t pixeldata = 0; for (int j = 0; j < 8; j++) { - if (da2->vram[(da2->vram_mask & (addr << 3)) | j] & (1 << (7 - index))) pixeldata++; + if (da2->vram[(da2->vram_mask & (addr << 3)) | j] & (1 << (7 - index))) + pixeldata++; } return pixeldata; } -void print_pixelbyte(uint32_t addr, da2_t* da2) { - for (int i = 0; i < 8; i++) - { +void +print_pixelbyte(uint32_t addr, da2_t *da2) +{ + for (int i = 0; i < 8; i++) { pclog("%X", pixel1tohex(addr, i, da2)); } } -void print_bytetobin(uint8_t b) { - for (int i = 0; i < 8; i++) - { - if(b & 0x80) +void +print_bytetobin(uint8_t b) +{ + for (int i = 0; i < 8; i++) { + if (b & 0x80) pclog("1"); else pclog("0"); b <<= 1; } } -//Convert internal char code to Shift JIS code -inline int isKanji1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); } -inline int isKanji2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); } -uint16_t IBMJtoSJIS(uint16_t knj) +// Convert internal char code to Shift JIS code +inline int +isKanji1(uint8_t chr) { - if (knj < 0x100) return 0xffff; + return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); +} +inline int +isKanji2(uint8_t chr) +{ + return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); +} +uint16_t +IBMJtoSJIS(uint16_t knj) +{ + if (knj < 0x100) + return 0xffff; knj -= 0x100; if (knj <= 0x1f7d) - ;/* do nothing */ + ; /* do nothing */ else if (knj >= 0xb700 && knj <= 0xb75f) { knj -= 0x90ec; - } - else if (knj >= 0xb3f0 && knj <= 0xb67f) { + } else if (knj >= 0xb3f0 && knj <= 0xb67f) { knj -= 0x906c; - } - else if (knj >= 0x8000 && knj <= 0x8183) - { + } else if (knj >= 0x8000 && knj <= 0x8183) { knj -= 0x5524; - } - else + } else return 0xffff; uint32_t knj1 = knj / 0xBC; uint32_t knj2 = knj - (knj1 * 0xBC); knj1 += 0x81; - if (knj1 > 0x9F) knj1 += 0x40; + if (knj1 > 0x9F) + knj1 += 0x40; knj2 += 0x40; - if (knj2 > 0x7E) knj2++; - //if (!isKanji1(knj1)) return 0xffff; - //if (!isKanji2(knj2)) return 0xffff; + if (knj2 > 0x7E) + knj2++; + // if (!isKanji1(knj1)) return 0xffff; + // if (!isKanji2(knj2)) return 0xffff; knj = knj1 << 8; knj |= knj2; return knj; } #endif -void da2_bitblt_load(da2_t* da2) +void +da2_bitblt_load(da2_t *da2) { uint32_t value32; uint64_t value64; da2_log("BITBLT loading params\n"); - //da2_log("BitBlt memory:\n"); - //if (da2->bitblt.payload[0] != 0) - // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) - // { - // int i = j * 8; - // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - // da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); - // } + // da2_log("BitBlt memory:\n"); + // if (da2->bitblt.payload[0] != 0) + // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) + // { + // int i = j * 8; + // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + // da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + // } int i = 0; - while (i < DA2_BLT_MEMSIZE) - { + while (i < DA2_BLT_MEMSIZE) { if (da2->bitblt.reg[0x20] & 0x1) break; switch (da2->bitblt.payload[i]) { - case 0x88: - case 0x89: - case 0x95: - value32 = da2->bitblt.payload[i + 3]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; - i += 3; - break; - case 0x91: - value32 = da2->bitblt.payload[i + 5]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 4]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 3]; - value32 <<= 8; - value32 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; - i += 5; - break; - case 0x99: - value64 = da2->bitblt.payload[i + 7]; - value64 <<= 8; - value64 = da2->bitblt.payload[i + 6]; - value64 <<= 8; - value64 = da2->bitblt.payload[i + 5]; - value64 <<= 8; - value64 |= da2->bitblt.payload[i + 4]; - value64 <<= 8; - value64 |= da2->bitblt.payload[i + 3]; - value64 <<= 8; - value64 |= da2->bitblt.payload[i + 2]; - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; - da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); - i += 7; - break; - case 0x00: - break; - default: - da2_log("da2_ParseBLT: Unknown PreOP!\n"); - break; + case 0x88: + case 0x89: + case 0x95: + value32 = da2->bitblt.payload[i + 3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 2]; + da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + i += 3; + break; + case 0x91: + value32 = da2->bitblt.payload[i + 5]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 4]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 3]; + value32 <<= 8; + value32 |= da2->bitblt.payload[i + 2]; + da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + i += 5; + break; + case 0x99: + value64 = da2->bitblt.payload[i + 7]; + value64 <<= 8; + value64 = da2->bitblt.payload[i + 6]; + value64 <<= 8; + value64 = da2->bitblt.payload[i + 5]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 4]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 3]; + value64 <<= 8; + value64 |= da2->bitblt.payload[i + 2]; + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; + da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + i += 7; + break; + case 0x00: + break; + default: + da2_log("da2_ParseBLT: Unknown PreOP!\n"); + break; } i++; } @@ -656,31 +675,31 @@ void da2_bitblt_load(da2_t* da2) memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); da2->bitblt.payload_addr = 0; /* [89] 20: 0001 (1) then execute payload */ - if (da2->bitblt.reg[0x20] & 0x1) - { + if (da2->bitblt.reg[0x20] & 0x1) { #ifdef ENABLE_DA2_DEBUGBLT for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { - //if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); + // if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); } for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; } da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * (da2->bitblt.debug_reg_ip + 1) - 1] = 0; da2->bitblt.debug_reg_ip++; - if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; + if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) + da2->bitblt.debug_reg_ip = 0; #endif - da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f);/* set bit shift */ - da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03;/* 01 AND, 03 XOR */ + da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ + da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03; /* 01 AND, 03 XOR */ da2_log("bitblt execute 05: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); for (int i = 0; i <= 0xb; i++) da2_log("%02x ", da2->gdcreg[i]); da2_log("\n"); - da2->bitblt.destaddr = da2->bitblt.reg[0x29]; - da2->bitblt.size_x = da2->bitblt.reg[0x33]; - da2->bitblt.size_y = da2->bitblt.reg[0x35]; + da2->bitblt.destaddr = da2->bitblt.reg[0x29]; + da2->bitblt.size_x = da2->bitblt.reg[0x33]; + da2->bitblt.size_y = da2->bitblt.reg[0x35]; da2->bitblt.destpitch = da2->bitblt.reg[0x21]; - da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; + da2->bitblt.srcpitch = da2->bitblt.reg[0x22]; if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ { da2->bitblt.destaddr -= 2; @@ -689,63 +708,61 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.srcpitch -= 2; } da2->bitblt.fcolor = da2->bitblt.reg[0x0]; - da2->bitblt.maskl = da2->bitblt.reg[0x8]; - da2->bitblt.maskr = da2->bitblt.reg[0x9]; - da2->bitblt.x = 0; - da2->bitblt.y = 0; - da2->bitblt.exec = DA2_BLT_CDONE; + da2->bitblt.maskl = da2->bitblt.reg[0x8]; + da2->bitblt.maskr = da2->bitblt.reg[0x9]; + da2->bitblt.x = 0; + da2->bitblt.y = 0; + da2->bitblt.exec = DA2_BLT_CDONE; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); if (da2->bitblt.reg[0x2f] < 0x80) /* MS Paint 3.1 will cause hang up in 256 color mode */ { da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); da2->bitblt.exec = DA2_BLT_CDONE; - } - else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ + } else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ da2->bitblt.exec = DA2_BLT_CPUTCHAR; /* Todo: addressing */ - //if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ + // if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ //{ - // da2->bitblt.destaddr += 2; - // da2->bitblt.size_x -= 1; - // da2->bitblt.destpitch += 2; - // da2->bitblt.srcpitch += 2; - //} + // da2->bitblt.destaddr += 2; + // da2->bitblt.size_x -= 1; + // da2->bitblt.destpitch += 2; + // da2->bitblt.srcpitch += 2; + // } da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2; da2->bitblt.destaddr += 2; - da2->bitblt.srcpitch = 0; + da2->bitblt.srcpitch = 0; da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ da2->bitblt.bitshift_destr += 1; #ifdef ENABLE_DA2_DEBUGBLT uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); #endif - } - else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { - da2->bitblt.exec = DA2_BLT_CPUTCHAR; + } else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { + da2->bitblt.exec = DA2_BLT_CPUTCHAR; da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; da2->bitblt.destaddr += 2; - da2->bitblt.srcpitch = 0; + da2->bitblt.srcpitch = 0; da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ da2->bitblt.bitshift_destr += 1; #ifdef ENABLE_DA2_DEBUGBLT uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; uint32_t sjis_l = IBMJtoSJIS(da2->bitblt.reg[0x12]) & 0xff; da2_log("put char src=%x, dest=%x, x=%d, y=%d, w=%d, h=%d, c=%c%c\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); #endif } /* Fill a rectangle(or draw a line) */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.reg[0x0], da2->bitblt.reg[0x2F], da2->rowoffset * 2); da2->bitblt.exec = DA2_BLT_CFILLRECT; da2->bitblt.destaddr += 2; } @@ -754,282 +771,270 @@ void da2_bitblt_load(da2_t* da2) da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; - da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); } /* Tiling a rectangle (transfer tile data multiple times) */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x40) { da2->bitblt.exec = DA2_BLT_CFILLTILE; da2->bitblt.destaddr += 2; da2->bitblt.srcaddr = da2->bitblt.reg[0x2B]; - da2->bitblt.tile_w = da2->bitblt.reg[0x28]; + da2->bitblt.tile_w = da2->bitblt.reg[0x28]; da2_log("copy tile src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2B] % (da2->rowoffset * 2), da2->bitblt.reg[0x2B] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); } /* Block transfer (range copy) */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) { - da2->bitblt.exec = DA2_BLT_CCOPYF; + da2->bitblt.exec = DA2_BLT_CCOPYF; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr += 2; da2_log("copy block src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", - da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - da2->bitblt.size_x, da2->bitblt.size_y); + da2->bitblt.srcaddr, da2->bitblt.destaddr, + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.size_x, da2->bitblt.size_y); } /* Block copy but reversed direction */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1140 && da2->bitblt.reg[0x3D] == 0x00) { - da2->bitblt.exec = DA2_BLT_CCOPYR; + da2->bitblt.exec = DA2_BLT_CCOPYR; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; da2->bitblt.destaddr -= 2; da2->bitblt.srcaddr -= 2; - da2_log("copy blockR src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", + da2_log("copy blockR src=%x, dest=%x, x1=%d, y1=%d, x2=%d, y2=%d, w=%d, h=%d\n", da2->bitblt.srcaddr, da2->bitblt.destaddr, - da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), - da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + da2->bitblt.reg[0x2A] % (da2->rowoffset * 2), da2->bitblt.reg[0x2A] / (da2->rowoffset * 2), + da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); - //da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); + // da2_log(" mask8=%x, mask9=%x\n", da2->bitblt.reg[0x8], da2->bitblt.reg[0x9]); } } } -void da2_bitblt_exec(void* p) +void +da2_bitblt_exec(void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - //da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); - switch (da2->bitblt.exec) - { - case DA2_BLT_CIDLE: - timer_disable(&da2->bitblt.timer); - break; - case DA2_BLT_CLOAD: - da2->bitblt.indata = 0; - da2_bitblt_load(da2); - break; - case DA2_BLT_CFILLRECT: - //da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; + // da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + switch (da2->bitblt.exec) { + case DA2_BLT_CIDLE: + timer_disable(&da2->bitblt.timer); + break; + case DA2_BLT_CLOAD: + da2->bitblt.indata = 0; + da2_bitblt_load(da2); + break; + case DA2_BLT_CFILLRECT: + // da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + } else if (da2->bitblt.x == 0) { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } else { + DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, 0xffff, da2); + da2->bitblt.x++; } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - } - else if (da2->bitblt.x == 0) { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_DrawColorWithBitmask(da2->bitblt.destaddr, da2->bitblt.fcolor, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr += 2; - break; - case DA2_BLT_CFILLTILE: - int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; + da2->bitblt.destaddr += 2; + break; + case DA2_BLT_CFILLTILE: + int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + } else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } else { + DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - } - else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr += 2; - break; - case DA2_BLT_CCOPYF: - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; + da2->bitblt.destaddr += 2; + break; + case DA2_BLT_CCOPYF: + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + da2->bitblt.srcaddr += da2->bitblt.srcpitch + 2; + } else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } else { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - da2->bitblt.srcaddr += da2->bitblt.srcpitch + 2; - } - else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr += 2; - da2->bitblt.srcaddr += 2; - break; - case DA2_BLT_CCOPYR: - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 1) - { - da2->bitblt.exec = DA2_BLT_CDONE; + da2->bitblt.destaddr += 2; + da2->bitblt.srcaddr += 2; + break; + case DA2_BLT_CCOPYR: + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 1) { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr -= da2->bitblt.destpitch; + da2->bitblt.srcaddr -= da2->bitblt.srcpitch; + da2->bitblt.destaddr -= 2; + da2->bitblt.srcaddr -= 2; + } else if (da2->bitblt.x == 0) { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + } else { + DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr -= da2->bitblt.destpitch; - da2->bitblt.srcaddr -= da2->bitblt.srcpitch; da2->bitblt.destaddr -= 2; da2->bitblt.srcaddr -= 2; - } - else if (da2->bitblt.x == 0) { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - } - else { - DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - } - da2->bitblt.destaddr -= 2; - da2->bitblt.srcaddr -= 2; - break; - case DA2_BLT_CPUTCHAR: - //da2->bitblt.y += 2; - da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; - //pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); - //da2->bitblt.srcaddr += 2; - if(da2->bitblt.reg[0x12] < 0x100) - da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; - else - da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; - //print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); - //print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); - //pclog("\n"); - if (da2->bitblt.x >= da2->bitblt.size_x - 1) { - //if (1) { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); - if (da2->bitblt.y >= da2->bitblt.size_y - 3) - { - da2->bitblt.exec = DA2_BLT_CDONE; + break; + case DA2_BLT_CPUTCHAR: + // da2->bitblt.y += 2; + da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; + // pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); + // da2->bitblt.srcaddr += 2; + if (da2->bitblt.reg[0x12] < 0x100) + da2->bitblt.srcaddr = DA2_FONTROM_BASESBCS + da2->bitblt.reg[0x12] * 64 + (da2->bitblt.x * 2) + (da2->bitblt.y * 2) - 2; + else + da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2) + (da2->bitblt.y * 3) - 2; + // print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 2]); + // print_bytetobin(da2->mmio.font[da2->bitblt.srcaddr + 3]); + // pclog("\n"); + if (da2->bitblt.x >= da2->bitblt.size_x - 1) { + // if (1) { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); + if (da2->bitblt.y >= da2->bitblt.size_y - 3) { + da2->bitblt.exec = DA2_BLT_CDONE; + } + da2->bitblt.x = 0; + da2->bitblt.y++; + da2->bitblt.destaddr += 130; + // da2->bitblt.destaddr += da2->bitblt.destpitch + 2; + // da2->bitblt.srcaddr += -1; + } else if (da2->bitblt.x == 0) { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); + da2->bitblt.x++; + // da2->bitblt.x++; + } else { + DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); + da2->bitblt.x++; + // da2->bitblt.x++; } - da2->bitblt.x = 0; - da2->bitblt.y++; - da2->bitblt.destaddr += 130; - //da2->bitblt.destaddr += da2->bitblt.destpitch + 2; - //da2->bitblt.srcaddr += -1; - } - else if (da2->bitblt.x == 0) { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskl, da2); - da2->bitblt.x++; - //da2->bitblt.x++; - } - else { - DA2_PutcharWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, 0xffff, da2); - da2->bitblt.x++; - //da2->bitblt.x++; - } - //da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2; - ////da2->bitblt.srcaddr += 2; - //da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; - break; - case DA2_BLT_CDONE: - /* initialize regs for debug dump */ - for (int i = 0; i < DA2_BLT_REGSIZE; i++) { - if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; - } - if(da2->bitblt.indata) da2->bitblt.exec = DA2_BLT_CLOAD; - else da2->bitblt.exec = DA2_BLT_CIDLE; - break; + // da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x + da2->bitblt.y * 130 + 2; + ////da2->bitblt.srcaddr += 2; + // da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; + break; + case DA2_BLT_CDONE: + /* initialize regs for debug dump */ + for (int i = 0; i < DA2_BLT_REGSIZE; i++) { + if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) + da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; + } + if (da2->bitblt.indata) + da2->bitblt.exec = DA2_BLT_CLOAD; + else + da2->bitblt.exec = DA2_BLT_CIDLE; + break; } } -void da2_bitblt_dopayload(da2_t* da2) { - if (da2->bitblt.exec == DA2_BLT_CIDLE) - { +void +da2_bitblt_dopayload(da2_t *da2) +{ + if (da2->bitblt.exec == DA2_BLT_CIDLE) { da2->bitblt.exec = DA2_BLT_CLOAD; - //timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + // timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ da2_log("da2 Do bitblt\n"); - while (da2->bitblt.exec != DA2_BLT_CIDLE) - { + while (da2->bitblt.exec != DA2_BLT_CIDLE) { da2_bitblt_exec(da2); } da2_log("da2 End bitblt %x\n", da2->bitblt.exec); } } -void da2_out(uint16_t addr, uint16_t val, void *p) +void +da2_out(uint16_t addr, uint16_t val, void *p) { - da2_t *da2 = (da2_t *)p; - int oldval; -/* -3E0 3E1 Sequencer Registers (undoc) -3E2 3E3 Font Registers (undoc) -3E4 3E5 CRT Control Registers (undoc) -3E8 3E9 Attribute Controller Registers (undoc) -3EA 3EB 3EC Graphics Contoller Registers -*/ - switch (addr) - { + da2_t *da2 = (da2_t *) p; + int oldval; + /* + 3E0 3E1 Sequencer Registers (undoc) + 3E2 3E3 Font Registers (undoc) + 3E4 3E5 CRT Control Registers (undoc) + 3E8 3E9 Attribute Controller Registers (undoc) + 3EA 3EB 3EC Graphics Contoller Registers + */ + switch (addr) { case 0x3c6: /* PEL Mask */ da2->dac_mask = val; break; case 0x3C7: /* Read Address */ da2->dac_read = val; - da2->dac_pos = 0; + da2->dac_pos = 0; break; case 0x3C8: /* Write Address */ da2->dac_write = val; - da2->dac_read = val - 1; - da2->dac_pos = 0; + da2->dac_read = val - 1; + da2->dac_pos = 0; break; case 0x3C9: /* Data */ - //da2_log("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI); + // da2_log("DA2 Out addr %03X idx %d:%d val %02X %04X:%04X esdi %04X:%04X\n", addr, da2->dac_write, da2->dac_pos, val, cs >> 4, cpu_state.pc, ES, DI); da2->dac_status = 0; da2->fullchange = changeframecount; - switch (da2->dac_pos) - { - case 0: - da2->dac_r = val; - da2->dac_pos++; - break; - case 1: - da2->dac_g = val; - da2->dac_pos++; - break; - case 2: - da2->vgapal[da2->dac_write].r = da2->dac_r; - da2->vgapal[da2->dac_write].g = da2->dac_g; - da2->vgapal[da2->dac_write].b = val; - //if (da2->ramdac_type == RAMDAC_8BIT) - // da2->pallook[da2->dac_write] = makecol32(da2->vgapal[da2->dac_write].r, da2->vgapal[da2->dac_write].g, da2->vgapal[da2->dac_write].b); - //else + switch (da2->dac_pos) { + case 0: + da2->dac_r = val; + da2->dac_pos++; + break; + case 1: + da2->dac_g = val; + da2->dac_pos++; + break; + case 2: + da2->vgapal[da2->dac_write].r = da2->dac_r; + da2->vgapal[da2->dac_write].g = da2->dac_g; + da2->vgapal[da2->dac_write].b = val; + // if (da2->ramdac_type == RAMDAC_8BIT) + // da2->pallook[da2->dac_write] = makecol32(da2->vgapal[da2->dac_write].r, da2->vgapal[da2->dac_write].g, da2->vgapal[da2->dac_write].b); + // else da2->pallook[da2->dac_write] = makecol32((da2->vgapal[da2->dac_write].r & 0x3f) * 4, (da2->vgapal[da2->dac_write].g & 0x3f) * 4, (da2->vgapal[da2->dac_write].b & 0x3f) * 4); - da2->dac_pos = 0; - da2->dac_write = (da2->dac_write + 1) & 255; - break; + da2->dac_pos = 0; + da2->dac_write = (da2->dac_write + 1) & 255; + break; } break; case LS_INDEX: da2->ioctladdr = val; break; case LS_DATA: - //da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->ioctladdr, val, cs >> 4, cpu_state.pc); - if (da2->ioctladdr > 0xf) return; + // da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->ioctladdr, val, cs >> 4, cpu_state.pc); + if (da2->ioctladdr > 0xf) + return; if (da2->ioctl[da2->ioctladdr & 15] != val) da2_log("ioctl changed %x: %x -> %x %04X:%04X\n", da2->ioctladdr & 15, da2->ioctl[da2->ioctladdr & 15], val, cs >> 4, cpu_state.pc); - oldval = da2->ioctl[da2->ioctladdr]; + oldval = da2->ioctl[da2->ioctladdr]; da2->ioctl[da2->ioctladdr] = val; if (oldval != val) { if (da2->ioctladdr == LS_RESET && val & 0x01) /* Reset register */ @@ -1039,10 +1044,9 @@ void da2_out(uint16_t addr, uint16_t val, void *p) da2->fullchange = changeframecount; da2_recalctimings(da2); da2_updatevidselector(da2); - } - else if (da2->ioctladdr == LS_MMIO && (!(val & 0x01))) /* MMIO register */ + } else if (da2->ioctladdr == LS_MMIO && (!(val & 0x01))) /* MMIO register */ { - //da2->bitblt.indata = 1; + // da2->bitblt.indata = 1; } } break; @@ -1050,14 +1054,14 @@ void da2_out(uint16_t addr, uint16_t val, void *p) da2->fctladdr = val; break; case LF_DATA: - //da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); - if (da2->fctladdr > 0x1f) return; + // da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); + if (da2->fctladdr > 0x1f) + return; if (da2->fctl[da2->fctladdr & 0x1f] != val) da2_log("fctl changed %x: %x -> %x %04X:%04X\n", da2->fctladdr & 0x1f, da2->fctl[da2->fctladdr & 0x1f], val, cs >> 4, cpu_state.pc); - oldval = da2->fctl[da2->fctladdr]; + oldval = da2->fctl[da2->fctladdr]; da2->fctl[da2->fctladdr] = val; - if (da2->fctladdr == 0 && oldval != val) - { + if (da2->fctladdr == 0 && oldval != val) { da2->fullchange = changeframecount; da2_recalctimings(da2); } @@ -1066,87 +1070,85 @@ void da2_out(uint16_t addr, uint16_t val, void *p) da2->crtcaddr = val; break; case LC_DATA: - if (da2->crtcaddr > 0x1f) return; - //if (!(da2->crtcaddr == LC_CURSOR_LOC_HIGH || da2->crtcaddr == LC_CURSOR_LOC_LOWJ)) - // da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc); - if (!(da2->crtc[da2->crtcaddr] ^ val)) return; + if (da2->crtcaddr > 0x1f) + return; + // if (!(da2->crtcaddr == LC_CURSOR_LOC_HIGH || da2->crtcaddr == LC_CURSOR_LOC_LOWJ)) + // da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc); + if (!(da2->crtc[da2->crtcaddr] ^ val)) + return; switch (da2->crtcaddr) { - case LC_CRTC_OVERFLOW: - //return; - break; - case LC_MAXIMUM_SCAN_LINE: - if (!(da2->ioctl[LS_MODE] & 0x01)) val = 0; - break; - case LC_START_ADDRESS_HIGH: - //if (da2->crtc[0x1c] & 0x40) return; - break; - case LC_VERTICAL_TOTALJ: /* Vertical Total */ - case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ - case LC_V_DISPLAY_ENABLE_END: /* Vertical Display End Register */ - case LC_START_VERTICAL_BLANK: /* Start Vertical Blank Register */ - //val = 0x400; //for debugging bitblt - break; - case LC_VIEWPORT_SELECT: /* ViewPort Select? */ - //return; - break; - case LC_VIEWPORT_NUMBER: /* Compatibility? */ - break; + case LC_CRTC_OVERFLOW: + // return; + break; + case LC_MAXIMUM_SCAN_LINE: + if (!(da2->ioctl[LS_MODE] & 0x01)) + val = 0; + break; + case LC_START_ADDRESS_HIGH: + // if (da2->crtc[0x1c] & 0x40) return; + break; + case LC_VERTICAL_TOTALJ: /* Vertical Total */ + case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ + case LC_V_DISPLAY_ENABLE_END: /* Vertical Display End Register */ + case LC_START_VERTICAL_BLANK: /* Start Vertical Blank Register */ + // val = 0x400; /* for debugging bitblt in Win 3.x */ + break; + case LC_VIEWPORT_SELECT: /* ViewPort Select? */ + // return; + break; + case LC_VIEWPORT_NUMBER: /* Compatibility? */ + break; } da2->crtc[da2->crtcaddr] = val; switch (da2->crtcaddr) { - case LC_H_DISPLAY_ENABLE_END: - case LC_VERTICAL_TOTALJ: - case LC_MAXIMUM_SCAN_LINE: - case LC_START_ADDRESS_HIGH: - case LC_START_ADDRESS_LOW: - case LC_VERTICAL_SYNC_START: - case LC_V_DISPLAY_ENABLE_END: - case LC_START_VERTICAL_BLANK: - case LC_END_VERTICAL_BLANK: - case LC_VIEWPORT_PRIORITY: - da2->fullchange = changeframecount; - da2_recalctimings(da2); - break; - default: - break; + case LC_H_DISPLAY_ENABLE_END: + case LC_VERTICAL_TOTALJ: + case LC_MAXIMUM_SCAN_LINE: + case LC_START_ADDRESS_HIGH: + case LC_START_ADDRESS_LOW: + case LC_VERTICAL_SYNC_START: + case LC_V_DISPLAY_ENABLE_END: + case LC_START_VERTICAL_BLANK: + case LC_END_VERTICAL_BLANK: + case LC_VIEWPORT_PRIORITY: + da2->fullchange = changeframecount; + da2_recalctimings(da2); + break; + default: + break; } break; case LV_PORT: - //da2_log("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc); - if (!da2->attrff) - { + // da2_log("DA2 Out addr %03X val %02X ff %d %04X:%04X\n", addr, val, da2->attrff,cs >> 4, cpu_state.pc); + if (!da2->attrff) { // da2->attraddr = val & 31; da2->attraddr = val & 0x3f; - if ((val & 0x20) != (da2->attr_palette_enable & 0x20)) - { - da2->fullchange = 3; + if ((val & 0x20) != (da2->attr_palette_enable & 0x20)) { + da2->fullchange = 3; da2->attr_palette_enable = val & 0x20; da2_recalctimings(da2); } - //da2_log("set attraddr: %X\n", da2->attraddr); - } - else - { + // da2_log("set attraddr: %X\n", da2->attraddr); + } else { if ((da2->attraddr == LV_PANNING) && (da2->attrc[LV_PANNING] != val)) da2->fullchange = changeframecount; if (da2->attrc[da2->attraddr & 0x3f] != val) da2_log("attr changed %x: %x -> %x\n", da2->attraddr & 0x3f, da2->attrc[da2->attraddr & 0x3f], val); da2->attrc[da2->attraddr & 0x3f] = val; - //da2_log("set attrc %x: %x\n", da2->attraddr & 31, val); + // da2_log("set attrc %x: %x\n", da2->attraddr & 31, val); if (da2->attraddr < 16) da2->fullchange = changeframecount; - if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) - { - for (int c = 0; c < 16; c++) - { - //if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4); - //else da2->egapal[c] = (da2->attrc[c] & 0x3f) | ((da2->attrc[0x14] & 0xc) << 4); - if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = da2->attrc[c] & 0xf; - else da2->egapal[c] = da2->attrc[c] & 0x3f; + if (da2->attraddr == LV_MODE_CONTROL || da2->attraddr < 0x10) { + for (int c = 0; c < 16; c++) { + // if (da2->attrc[LV_MODE_CONTROL] & 0x80) da2->egapal[c] = (da2->attrc[c] & 0xf) | ((da2->attrc[0x14] & 0xf) << 4); + // else da2->egapal[c] = (da2->attrc[c] & 0x3f) | ((da2->attrc[0x14] & 0xc) << 4); + if (da2->attrc[LV_MODE_CONTROL] & 0x80) + da2->egapal[c] = da2->attrc[c] & 0xf; + else + da2->egapal[c] = da2->attrc[c] & 0x3f; } } - switch (da2->attraddr) - { + switch (da2->attraddr) { case LV_COLOR_PLANE_ENAB: if ((val & 0xff) != da2->plane_mask) da2->fullchange = changeframecount; @@ -1154,15 +1156,15 @@ void da2_out(uint16_t addr, uint16_t val, void *p) break; case LV_CURSOR_CONTROL: switch (val & 0x18) { - case 0x08://fast blink - da2->blinkconf = 0x10; - break; - case 0x18://slow blink - da2->blinkconf = 0x20; - break; - default://no blink - da2->blinkconf = 0xff; - break; + case 0x08: /* fast blink */ + da2->blinkconf = 0x10; + break; + case 0x18: /* slow blink */ + da2->blinkconf = 0x20; + break; + default: /* no blink */ + da2->blinkconf = 0xff; + break; } break; case LV_MODE_CONTROL: @@ -1184,79 +1186,81 @@ void da2_out(uint16_t addr, uint16_t val, void *p) da2->gdcaddr = val; break; case LG_DATA: - //if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); - //if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI); - switch (da2->gdcaddr & 0x1f) - { - case LG_READ_MAP_SELECT: - da2->readplane = val & 0x7; - break; - case LG_MODE: - da2->writemode = val & 3; - break; - case LG_MAP_MASKJ: - da2->writemask = val & 0xff; - break; - case LG_COMMAND: - break; - case LG_SET_RESET_2: - da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); - return; + // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); + // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI); + switch (da2->gdcaddr & 0x1f) { + case LG_READ_MAP_SELECT: + da2->readplane = val & 0x7; + break; + case LG_MODE: + da2->writemode = val & 3; + break; + case LG_MAP_MASKJ: + da2->writemask = val & 0xff; + break; + case LG_COMMAND: + break; + case LG_SET_RESET_2: + da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); + return; } da2->gdcreg[da2->gdcaddr & 15] = val & 0xff; break; - //case 0x3ed: /* used by Windows 3.1 display driver */ - // da2->gdcreg[5] = val & 0xff; - // break; + // case 0x3ed: /* used by Windows 3.1 display driver */ + // da2->gdcreg[5] = val & 0xff; + // break; default: da2_log("DA2? Out addr %03X val %02X\n", addr, val); break; - } + } } -uint16_t da2_in(uint16_t addr, void *p) +uint16_t +da2_in(uint16_t addr, void *p) { - da2_t * da2 = (da2_t *)p; - uint16_t temp; + da2_t *da2 = (da2_t *) p; + uint16_t temp; - switch (addr) - { + switch (addr) { case 0x3c3: temp = 0; break; - case 0x3c6: temp = da2->dac_mask; + case 0x3c6: + temp = da2->dac_mask; break; - case 0x3c7: temp = da2->dac_status; + case 0x3c7: + temp = da2->dac_status; break; - case 0x3c8: temp = da2->dac_write; + case 0x3c8: + temp = da2->dac_write; break; case 0x3c9: da2->dac_status = 3; - switch (da2->dac_pos) - { - case 0: - da2->dac_pos++; - temp = da2->vgapal[da2->dac_read].r & 0x3f; - break; - case 1: - da2->dac_pos++; - temp = da2->vgapal[da2->dac_read].g & 0x3f; - break; - case 2: - da2->dac_pos = 0; - da2->dac_read = (da2->dac_read + 1) & 255; - temp = da2->vgapal[(da2->dac_read - 1) & 255].b & 0x3f; - break; + switch (da2->dac_pos) { + case 0: + da2->dac_pos++; + temp = da2->vgapal[da2->dac_read].r & 0x3f; + break; + case 1: + da2->dac_pos++; + temp = da2->vgapal[da2->dac_read].g & 0x3f; + break; + case 2: + da2->dac_pos = 0; + da2->dac_read = (da2->dac_read + 1) & 255; + temp = da2->vgapal[(da2->dac_read - 1) & 255].b & 0x3f; + break; } break; case LS_INDEX: temp = da2->ioctladdr; break; case LS_DATA: - //da2->ioctl[3] = 0x80; /* 3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) */ - if (da2->ioctladdr > 0xf) return DA2_INVALIDACCESS8; + // da2->ioctl[3] = 0x80; /* 3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) */ + if (da2->ioctladdr > 0xf) + return DA2_INVALIDACCESS8; temp = da2->ioctl[da2->ioctladdr]; - if (da2->ioctladdr == LS_STATUS) { /* Status register */ + if (da2->ioctladdr == LS_STATUS) { /* Status register */ if (da2->attrc[LV_COMPATIBILITY] & 0x08) { /* for detecting monitor type and cable wiring */ if (da2->monitorid == DA2_DCONFIG_MONTYPE_MONO) { /* grayscale monitor */ @@ -1275,54 +1279,54 @@ uint16_t da2_in(uint16_t addr, void *p) } else { temp |= 0x80; } - temp &= 0xf6;//clear busy bits + temp &= 0xf6; /* clear busy bit */ if (da2->bitblt.indata) /* for OS/2 J1.3 */ da2_bitblt_dopayload(da2); - if (da2->bitblt.exec != DA2_BLT_CIDLE) - { - //da2_log("exec:%x\n", da2->bitblt.exec); - temp |= 0x08;//wait(bit 3 + bit 0) - //if (!da2->bitblt.timer.enabled) + if (da2->bitblt.exec != DA2_BLT_CIDLE) { + // da2_log("exec:%x\n", da2->bitblt.exec); + temp |= 0x08; // wait(bit 3 + bit 0) + // if (!da2->bitblt.timer.enabled) //{ - // da2_log("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); - // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - //} + // da2_log("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); + // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + // } } if (da2->bitblt.indata) temp |= 0x01; - //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); } - //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); break; case LF_INDEX: temp = da2->fctladdr; break; case LF_DATA: - if (da2->fctladdr > 0x1f) return DA2_INVALIDACCESS8; + if (da2->fctladdr > 0x1f) + return DA2_INVALIDACCESS8; temp = da2->fctl[da2->fctladdr]; break; case LC_INDEX: temp = da2->crtcaddr; break; case LC_DATA: - if (da2->crtcaddr > 0x1f) return DA2_INVALIDACCESS8; + if (da2->crtcaddr > 0x1f) + return DA2_INVALIDACCESS8; temp = da2->crtc[da2->crtcaddr]; break; case LV_PORT: temp = da2->attraddr | da2->attr_palette_enable; break; case 0x3E9: - if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this maybe equivalent to 3ba / 3da Input Status Register 1 */ + if (da2->attraddr == LV_RAS_STATUS_VIDEO) /* this maybe equivalent to 3ba / 3da ISR1 */ { if (da2->cgastat & 0x01) da2->cgastat &= ~0x30; else da2->cgastat ^= 0x30; temp = da2->cgastat; - } - else + } else temp = da2->attrc[da2->attraddr]; - //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->attraddr, temp, cs >> 4, cpu_state.pc); + // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->attraddr, temp, cs >> 4, cpu_state.pc); da2->attrff = 0; /* reset flipflop (VGA does not reset flipflop) */ break; case LG_INDEX: @@ -1330,149 +1334,145 @@ uint16_t da2_in(uint16_t addr, void *p) break; case LG_DATA: temp = da2->gdcreg[da2->gdcaddr & 0x1f]; - //da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc); + // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->gdcaddr, temp, cs >> 4, cpu_state.pc); break; - } - //da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); - return temp; + } + // da2_log("DA2 In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + 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) -*/ -void da2_outb(uint16_t addr, uint8_t val, void* p) + * 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) + */ +void +da2_outb(uint16_t addr, uint8_t val, void *p) { - da2_t* da2 = (da2_t*)p; - //da2_log("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); + da2_t *da2 = (da2_t *) p; + // da2_log("DA2 Outb addr %03X val %02X %04X:%04X es:di=%x:%x ds:si=%x:%x\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); da2->inflipflop = 0; - switch (addr) - { - case LS_DATA: - case LF_DATA: - case LC_DATA: - case LG_DATA: - if (da2->outflipflop) - { - /* out b(idx), out b(data), out b(data) */ - da2->iolatch |= (uint16_t)val << 8; + switch (addr) { + case LS_DATA: + case LF_DATA: + case LC_DATA: + case LG_DATA: + if (da2->outflipflop) { + /* out b(idx), out b(data), out b(data) */ + da2->iolatch |= (uint16_t) val << 8; + da2->outflipflop = 0; + } else { // + da2->iolatch = val; + da2->outflipflop = 1; + } + break; + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + default: + da2->iolatch = val; da2->outflipflop = 0; - } - else - {// - da2->iolatch = val; - da2->outflipflop = 1; - } - break; - case LS_INDEX: - case LF_INDEX: - case LC_INDEX: - case LG_INDEX: - default: - da2->iolatch = val; - da2->outflipflop = 0; - break; + break; } da2_out(addr, da2->iolatch, da2); } -void da2_outw(uint16_t addr, uint16_t val, void* p) +void +da2_outw(uint16_t addr, uint16_t val, void *p) { - //da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - da2_t* da2 = (da2_t*)p; + da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_t *da2 = (da2_t *) p; da2->inflipflop = 0; - switch (addr) - { - case LS_INDEX: - case LF_INDEX: - case LC_INDEX: - case LG_INDEX: - da2_out(addr, val & 0xff, da2); - da2->iolatch = val >> 8; - da2_out(addr + 1, da2->iolatch, da2); - da2->outflipflop = 1; - break; - case LV_PORT: - da2->attrff = 0; + switch (addr) { + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + da2_out(addr, val & 0xff, da2); + da2->iolatch = val >> 8; + da2_out(addr + 1, da2->iolatch, da2); + da2->outflipflop = 1; + break; + case LV_PORT: + da2->attrff = 0; da2_out(addr, val & 0xff, da2); da2_out(addr, val >> 8, da2); da2->outflipflop = 0; - break; - case 0x3EC: - //da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - da2_out(LG_DATA, val >> 8, da2); - break; - case 0x3ED: - da2->gdcaddr = LG_MODE; - da2_out(LG_DATA, val, da2); - break; - case LS_DATA: - case LF_DATA: - case LC_DATA: - case LG_DATA: - default: - da2_out(addr, val, da2); - da2->outflipflop = 0; - break; - case 0x3EE: - da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - da2->reg3ee[val & 0xff] = val >> 8; - break; + break; + case 0x3EC: + // da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_out(LG_DATA, val >> 8, da2); + break; + case 0x3ED: + da2->gdcaddr = LG_MODE; + da2_out(LG_DATA, val, da2); + break; + case LS_DATA: + case LF_DATA: + case LC_DATA: + case LG_DATA: + default: + da2_out(addr, val, da2); + da2->outflipflop = 0; + break; + case 0x3EE: + da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2->reg3ee[val & 0xff] = val >> 8; + break; } } -uint8_t da2_inb(uint16_t addr, void* p) +uint8_t +da2_inb(uint16_t addr, void *p) { uint8_t temp; - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; da2->outflipflop = 0; - switch (addr) - { - case LC_DATA: - if (da2->inflipflop) - { - /* out b(idx), in b(low data), in b(high data) */ - temp = da2->iolatch >> 8; + switch (addr) { + case LC_DATA: + if (da2->inflipflop) { + /* out b(idx), in b(low data), in b(high data) */ + temp = da2->iolatch >> 8; + da2->inflipflop = 0; + } else { // + da2->iolatch = da2_in(addr, da2); + temp = da2->iolatch & 0xff; + da2->inflipflop = 1; + } + break; + case LS_INDEX: + case LF_INDEX: + case LC_INDEX: + case LG_INDEX: + case LS_DATA: + case LF_DATA: + case LG_DATA: + default: + temp = da2_in(addr, da2) & 0xff; da2->inflipflop = 0; - } - else - {// - da2->iolatch = da2_in(addr, da2); - temp = da2->iolatch & 0xff; - da2->inflipflop = 1; - } - break; - case LS_INDEX: - case LF_INDEX: - case LC_INDEX: - case LG_INDEX: - case LS_DATA: - case LF_DATA: - case LG_DATA: - default: - temp = da2_in(addr, da2) & 0xff; - da2->inflipflop = 0; - break; + break; } - //da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + // da2_log("DA2 Inb %04X %02X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); return temp; } -uint16_t da2_inw(uint16_t addr, void* p) +uint16_t +da2_inw(uint16_t addr, void *p) { - //uint16_t temp; - da2_t* da2 = (da2_t*)p; - da2->inflipflop = 0; + // uint16_t temp; + da2_t *da2 = (da2_t *) p; + da2->inflipflop = 0; da2->outflipflop = 0; return da2_in(addr, da2); } -/* IO 03DAh : Input Status Register 2 for DOSSHELL in DOS J4.0 */ -uint8_t da2_in_ISR(uint16_t addr, void* p) +/* IO 03DAh : Input Status Register 2 for DOSSHELL used by DOS J4.0 */ +uint8_t +da2_in_ISR(uint16_t addr, void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; uint8_t temp = 0; if (addr == 0x3da) { if (da2->cgastat & 0x01) @@ -1481,13 +1481,14 @@ uint8_t da2_in_ISR(uint16_t addr, void* p) da2->cgastat ^= 0x30; temp = da2->cgastat; } - //da2_log("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); + // da2_log("DA2D In %04X %04X %04X:%04X\n", addr, temp, cs >> 4, cpu_state.pc); return temp; } -void da2_out_ISR(uint16_t addr, uint8_t val, void* p) +void +da2_out_ISR(uint16_t addr, uint8_t val, void *p) { - //da2_t* da2 = (da2_t*)p; + // da2_t* da2 = (da2_t*)p; da2_log("DA2D Out %04X %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); } @@ -1592,29 +1593,30 @@ The Font ROM can be accessed via 128 KB memory window located at A0000-BFFFFh. */ /* Get character line pattern from jfont rom or gaiji volatile memory */ -uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void* p) { - da2_t* da2 = (da2_t*)p; - uint32_t font = 0; - int32_t fline = line - 2;/* Start line of drawing character (line >= 1 AND line < 24 + 1 ) */ - if (code >= 0x8000 && code <= 0x8183) code -= 0x6000;//shift for IBM extended characters (I don't know how the real card works.) */ +uint32_t +getfont_ps55dbcs(int32_t code, int32_t line, void *p) +{ + da2_t *da2 = (da2_t *) p; + uint32_t font = 0; + int32_t fline = line - 2; /* Start line of drawing character (line >= 1 AND line < 24 + 1 ) */ + if (code >= 0x8000 && code <= 0x8183) + code -= 0x6000; /* shift for IBM extended characters (I don't know how the real card works.) */ if (code < DA2_FONTROM_SIZE / 72 && fline >= 0 && fline < 24) { - font = da2->mmio.font[code * 72 + fline * 3]; /* 1111 1111 */ - font <<= 8; /* 1111 1111 0000 0000 */ - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; /* 1111 1111 2222 0000 */ - font >>= 1; /* 0111 1111 1222 2000 */ - font <<= 4; /* 0111 1111 1222 2000 0000 */ - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; /* 0111 1111 1222 2000 2222 */ - font <<= 8; /* 0111 1111 1222 2000 2222 0000 0000 */ - font |= da2->mmio.font[code * 72 + fline * 3 + 2]; /* 0111 1111 1222 2000 2222 3333 3333 */ - font <<= 4; /* 0111 1111 1222 2000 2222 3333 3333 0000 */ + font = da2->mmio.font[code * 72 + fline * 3]; /* 1111 1111 */ + font <<= 8; /* 1111 1111 0000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; /* 1111 1111 2222 0000 */ + font >>= 1; /* 0111 1111 1222 2000 */ + font <<= 4; /* 0111 1111 1222 2000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; /* 0111 1111 1222 2000 2222 */ + font <<= 8; /* 0111 1111 1222 2000 2222 0000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 2]; /* 0111 1111 1222 2000 2222 3333 3333 */ + font <<= 4; /* 0111 1111 1222 2000 2222 3333 3333 0000 */ /* font >>= 1;//put blank at column 1 (and 26) */ - } - else if (code >= 0xb000 && code <= 0xb75f) - { + } else if (code >= 0xb000 && code <= 0xb75f) { /* convert code->address in gaiji memory */ code -= 0xb000; code *= 0x80; - //code += 0xf800; + // code += 0xf800; font = da2->mmio.ram[code + line * 4]; font <<= 8; font |= da2->mmio.ram[code + line * 4 + 1]; @@ -1622,8 +1624,7 @@ uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void* p) { font |= da2->mmio.ram[code + line * 4 + 2]; font <<= 8; font |= da2->mmio.ram[code + line * 4 + 3]; - } - else if (code > DA2_FONTROM_SIZE) + } else if (code > DA2_FONTROM_SIZE) font = 0xffffffff; else font = 0; @@ -1631,23 +1632,27 @@ uint32_t getfont_ps55dbcs(int32_t code, int32_t line, void* p) { } /* Reverse the bit order of attribute code IRGB to BGRI(used in Mode 3 and Cursor Color) */ -uint8_t IRGBtoBGRI(uint8_t attr) +uint8_t +IRGBtoBGRI(uint8_t attr) { attr = ((attr & 0x01) << 7) | ((attr & 0x02) << 5) | ((attr & 0x04) << 3) | ((attr & 0x08) << 1); return attr >>= 4; } /* Get the foreground color from the attribute byte */ -uint8_t getPS55ForeColor(uint8_t attr, da2_t* da2) +uint8_t +getPS55ForeColor(uint8_t attr, da2_t *da2) { - uint8_t foreground = ~attr & 0x08;// 0000 1000 */ - foreground <<= 2; /* 0010 0000 */ - foreground |= ~attr & 0xc0;/* 1110 0000 */ - foreground >>= 4;/* 0000 1110 */ - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) foreground |= 0x01;/* bright color palette */ + uint8_t foreground = ~attr & 0x08; /* 0000 1000 */ + foreground <<= 2; /* 0010 0000 */ + foreground |= ~attr & 0xc0; /* 1110 0000 */ + foreground >>= 4; /* 0000 1110 */ + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x40) + foreground |= 0x01; /* bright color palette */ return foreground; } -void da2_render_blank(da2_t* da2) +void +da2_render_blank(da2_t *da2) { int x, xx; @@ -1655,67 +1660,68 @@ void da2_render_blank(da2_t* da2) da2->firstline_draw = da2->displine; da2->lastline_draw = da2->displine; - for (x = 0; x < da2->hdisp; x++) - { - for (xx = 0; xx < 13; xx++) ((uint32_t*)buffer32->line[da2->displine])[(x * 13) + xx + 32] = 0; + for (x = 0; x < da2->hdisp; x++) { + for (xx = 0; xx < 13; xx++) + ((uint32_t *) buffer32->line[da2->displine])[(x * 13) + xx + 32] = 0; } } /* Display Adapter Mode 8, E Drawing */ -static void da2_render_text(da2_t* da2) +static void +da2_render_text(da2_t *da2) { if (da2->firstline_draw == 2000) da2->firstline_draw = da2->displine; da2->lastline_draw = da2->displine; - if (da2->fullchange) - { - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - int x; - int drawcursor; - uint8_t chr, attr; - int fg, bg; - uint32_t chr_dbcs; - int chr_wide = 0; - //da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); - for (x = 0; x < da2->hdisp; x += 13) - { - chr = da2->cram[(da2->ma) & da2->vram_display_mask]; + if (da2->fullchange) { + int offset = (8 - da2->scrollcache) + 24; + uint32_t *p = &((uint32_t *) buffer32->line[da2->displine])[offset]; + int x; + int drawcursor; + uint8_t chr, attr; + int fg, bg; + uint32_t chr_dbcs; + int chr_wide = 0; + // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); + for (x = 0; x < da2->hdisp; x += 13) { + chr = da2->cram[(da2->ma) & da2->vram_display_mask]; attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; - //if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); - if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80)/* 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) */ + // if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); + if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) /* 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, da2); - if (attr & 0x04) {/* reverse 0000 0100 */ + 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 */ + } 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 */ + attr &= 0x33; /* disable blinkking, underscore, highlight and reverse */ } - if (attr & 0x04) {/* reverse 0000 0100 */ + if (attr & 0x04) { /* reverse 0000 0100 */ bg = fg; fg = 0; } /* Blinking 1000 0000 */ fg = ((da2->blink & 0x20) || (!(attr & 0x80))) ? fg : bg; - //if(chr!=0x20) da2_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, da2->egapal[fg], da2->pallook[da2->egapal[fg]]); + // if(chr!=0x20) da2_log("chr: %x, %x, %x, %x, %x ", chr, attr, fg, da2->egapal[fg], da2->pallook[da2->egapal[fg]]); } /* Draw character */ - for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];/* draw blank */ + for (uint32_t n = 0; n < 13; n++) + p[n] = da2->pallook[da2->egapal[bg]]; /* draw blank */ /* SBCS or DBCS left half */ if (chr_wide == 0) { - if (attr & 0x01) chr_wide = 1; - //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 */ @@ -1729,18 +1735,17 @@ static void da2_render_text(da2_t* da2) p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; font <<= 1; } - } - else { + } else { /* the char code is SBCS (ANK) */ uint32_t fontbase; - if (attr & 0x02)/* second map of SBCS font */ + if (attr & 0x02) /* second map of SBCS font */ fontbase = DA2_GAIJIRAM_SBEX; else fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];/* w13xh29 font */ + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];/* w13xh29 font */ - //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ + // if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; @@ -1749,8 +1754,7 @@ static void da2_render_text(da2_t* da2) } } /* right half of DBCS */ - else - { + else { uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { @@ -1760,27 +1764,26 @@ static void da2_render_text(da2_t* da2) chr_wide = 0; } /* Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. */ - if (da2->sc == 27 && attr & 0x40 && ~da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) {/* Underscore only in monochrome mode */ + if (da2->sc == 27 && attr & 0x40 && ~da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) { /* Underscore only in monochrome mode */ for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[fg]];/* under line (white) */ + p[n] = da2->pallook[da2->egapal[fg]]; /* under line (white) */ } /* Column 1 (Vertical Line) */ if (attr & 0x10) { - p[0] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];/* vertical line (white) */ + p[0] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* vertical line (white) */ } - if (da2->sc == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) {/* HGrid */ + if (da2->sc == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) { /* HGrid */ for (uint32_t n = 0; n < 13; n++) - p[n] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]];/* horizontal line (white) */ + p[n] = da2->pallook[da2->egapal[(da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* horizontal line (white) */ } /* Drawing text cursor */ drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); - if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) - { + if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) { int cursorwidth = (da2->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13); - int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2;/* Choose color 2 if mode 8 */ - fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2); - bg = 0; - if (attr & 0x04) {/* Color 0 if reverse */ + int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2; /* Choose color 2 if mode 8 */ + fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2); + bg = 0; + if (attr & 0x04) { /* Color 0 if reverse */ bg = fg; fg = 0; } @@ -1794,45 +1797,46 @@ static void da2_render_text(da2_t* da2) p += 13; } da2->ma &= da2->vram_display_mask; - //da2->writelines++; + // da2->writelines++; } } /* Display Adapter Mode 3 Drawing */ -static void da2_render_textm3(da2_t* da2) +static void +da2_render_textm3(da2_t *da2) { if (da2->firstline_draw == 2000) da2->firstline_draw = da2->displine; da2->lastline_draw = da2->displine; - if (da2->fullchange) - { - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - int x; - int drawcursor; - uint8_t chr, attr, extattr; - int fg, bg; - uint32_t chr_dbcs; - int chr_wide = 0; - //da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); - for (x = 0; x < da2->hdisp; x += 13) - { - chr = da2->vram[(0x18000 + (da2->ma)) & da2->vram_mask]; - attr = da2->vram[((0x18000 + (da2->ma)) + 1) & da2->vram_mask]; + if (da2->fullchange) { + int offset = (8 - da2->scrollcache) + 24; + uint32_t *p = &((uint32_t *) buffer32->line[da2->displine])[offset]; + int x; + int drawcursor; + uint8_t chr, attr, extattr; + int fg, bg; + uint32_t chr_dbcs; + int chr_wide = 0; + // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); + for (x = 0; x < da2->hdisp; x += 13) { + chr = da2->vram[(0x18000 + (da2->ma)) & da2->vram_mask]; + attr = da2->vram[((0x18000 + (da2->ma)) + 1) & da2->vram_mask]; extattr = da2->vram[((0x10000 + (da2->ma)) + 1) & da2->vram_mask]; - //if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (0x18000 + da2->ma << 1) & da2->vram_mask, chr, attr); + // if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (0x18000 + da2->ma << 1) & da2->vram_mask, chr, attr); bg = attr >> 4; - //if (da2->blink) bg &= ~0x8; - //fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg; + // if (da2->blink) bg &= ~0x8; + // fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg; fg = attr & 0xf; fg = IRGBtoBGRI(fg); bg = IRGBtoBGRI(bg); /* Draw character */ - for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[bg]];/* draw blank */ + for (uint32_t n = 0; n < 13; n++) + p[n] = da2->pallook[da2->egapal[bg]]; /* draw blank */ /* BCS or DBCS left half */ if (chr_wide == 0) { - if (extattr & 0x01) chr_wide = 1; + if (extattr & 0x01) + chr_wide = 1; /* 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 */ @@ -1846,15 +1850,14 @@ static void da2_render_textm3(da2_t* da2) p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]]; font <<= 1; } - } - else { + } else { /* the char code is SBCS (ANK) */ uint32_t fontbase; - fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2];/* w13xh29 font */ + fontbase = DA2_GAIJIRAM_SBCS; + uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1];/* w13xh29 font */ - //if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ + // if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; font <<= 1; @@ -1862,8 +1865,7 @@ static void da2_render_textm3(da2_t* da2) } } /* right half of DBCS */ - else - { + else { uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2); /* Draw 13 dots */ for (uint32_t n = 0; n < 13; n++) { @@ -1873,16 +1875,15 @@ static void da2_render_textm3(da2_t* da2) chr_wide = 0; } drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron); - if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) - { - //int cursorwidth = (da2->crtc[0x1f] & 0x20 ? 26 : 13); - //int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;/* Choose color 2 if mode 8 */ - //fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; - //bg = 0; - //if (attr & 0x04) {/* Color 0 if reverse */ - // bg = fg; - // fg = 0; - //} + if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) { + // int cursorwidth = (da2->crtc[0x1f] & 0x20 ? 26 : 13); + // int cursorcolor = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;/* Choose color 2 if mode 8 */ + // fg = (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2; + // bg = 0; + // if (attr & 0x04) {/* Color 0 if reverse */ + // bg = fg; + // fg = 0; + // } for (uint32_t n = 0; n < 13; n++) p[n] = da2->pallook[da2->egapal[fg]]; } @@ -1890,562 +1891,550 @@ static void da2_render_textm3(da2_t* da2) p += 13; } da2->ma &= da2->vram_display_mask; - //da2->writelines++; + // da2->writelines++; } } -void da2_render_color_4bpp(da2_t* da2) +void +da2_render_color_4bpp(da2_t *da2) { int changed_offset = da2->ma >> 12; - //da2_log("ma %x cf %x\n", da2->ma, changed_offset); + // da2_log("ma %x cf %x\n", da2->ma, changed_offset); da2->plane_mask &= 0x0f; /*safety */ - if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) - { - int x; - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; + if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) { + int x; + int offset = (8 - da2->scrollcache) + 24; + uint32_t *p = &((uint32_t *) buffer32->line[da2->displine])[offset]; if (da2->firstline_draw == 2000) da2->firstline_draw = da2->displine; da2->lastline_draw = da2->displine; - //da2_log("d %X\n", da2->ma); - - for (x = 0; x <= da2->hdisp; x += 8)/* hdisp = 1024 */ - { - uint8_t edat[8]; - uint8_t dat; - - /* get 8 pixels from vram */ - da2->ma &= da2->vram_display_mask; - *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); - da2->ma += 1; - - dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)); - p[0] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)); - p[1] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)); - p[2] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)); - p[3] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)); - p[4] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)); - p[5] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)); - p[6] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)); - p[7] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; - p += 8; - } - //da2->writelines++; - } -} - -void da2_render_color_8bpp(da2_t* da2) -{ - int changed_offset = da2->ma >> 12; - //da2_log("ma %x cf %x\n", da2->ma, changed_offset); - - if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) - { - int x; - int offset = (8 - da2->scrollcache) + 24; - uint32_t* p = &((uint32_t*)buffer32->line[da2->displine])[offset]; - - if (da2->firstline_draw == 2000) - da2->firstline_draw = da2->displine; - da2->lastline_draw = da2->displine; - //da2_log("d %X\n", da2->ma); + // da2_log("d %X\n", da2->ma); for (x = 0; x <= da2->hdisp; x += 8) /* hdisp = 1024 */ { uint8_t edat[8]; uint8_t dat; - //get 8 pixels from vram + /* get 8 pixels from vram */ da2->ma &= da2->vram_display_mask; - *(uint32_t*)(&edat[0]) = *(uint32_t*)(&da2->vram[da2->ma << 3]); - *(uint32_t*)(&edat[4]) = *(uint32_t*)(&da2->vram[(da2->ma << 3) + 4]); + *(uint32_t *) (&edat[0]) = *(uint32_t *) (&da2->vram[da2->ma << 3]); da2->ma += 1; - dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)) | - ((edat[4] >> 3) & (1 << 4)) | ((edat[5] >> 2) & (1 << 5)) | ((edat[6] >> 1) & (1 << 6)) | ((edat[7] >> 0) & (1 << 7)); - p[0] = da2->pallook[dat]; - dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)) | - ((edat[4] >> 2) & (1 << 4)) | ((edat[5] >> 1) & (1 << 5)) | ((edat[6] >> 0) & (1 << 6)) | ((edat[7] << 1) & (1 << 7)); - p[1] = da2->pallook[dat]; - dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)) | - ((edat[4] >> 1) & (1 << 4)) | ((edat[5] >> 0) & (1 << 5)) | ((edat[6] << 1) & (1 << 6)) | ((edat[7] << 2) & (1 << 7)); - p[2] = da2->pallook[dat]; - dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)) | - ((edat[4] >> 0) & (1 << 4)) | ((edat[5] << 1) & (1 << 5)) | ((edat[6] << 2) & (1 << 6)) | ((edat[7] << 3) & (1 << 7)); - p[3] = da2->pallook[dat]; - dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)) | - ((edat[4] << 1) & (1 << 4)) | ((edat[5] << 2) & (1 << 5)) | ((edat[6] << 3) & (1 << 6)) | ((edat[7] << 4) & (1 << 7)); - p[4] = da2->pallook[dat]; - dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)) | - ((edat[4] << 2) & (1 << 4)) | ((edat[5] << 3) & (1 << 5)) | ((edat[6] << 4) & (1 << 6)) | ((edat[7] << 5) & (1 << 7)); - p[5] = da2->pallook[dat]; - dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)) | - ((edat[4] << 3) & (1 << 4)) | ((edat[5] << 4) & (1 << 5)) | ((edat[6] << 5) & (1 << 6)) | ((edat[7] << 6) & (1 << 7)); - p[6] = da2->pallook[dat]; - dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)) | - ((edat[4] << 4) & (1 << 4)) | ((edat[5] << 5) & (1 << 5)) | ((edat[6] << 6) & (1 << 6)) | ((edat[7] << 7) & (1 << 7)); - p[7] = da2->pallook[dat]; + dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)); + p[0] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)); + p[1] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)); + p[2] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)); + p[3] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)); + p[4] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)); + p[5] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)); + p[6] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; + dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)); + p[7] = da2->pallook[da2->egapal[dat & da2->plane_mask]]; p += 8; } - //da2->writelines++; + // da2->writelines++; } } -void da2_updatevidselector(da2_t* da2) { - /* if VGA passthrough mode */ +void +da2_render_color_8bpp(da2_t *da2) +{ + int changed_offset = da2->ma >> 12; + // da2_log("ma %x cf %x\n", da2->ma, changed_offset); + + if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) { + int x; + int offset = (8 - da2->scrollcache) + 24; + uint32_t *p = &((uint32_t *) buffer32->line[da2->displine])[offset]; + + if (da2->firstline_draw == 2000) + da2->firstline_draw = da2->displine; + da2->lastline_draw = da2->displine; + // da2_log("d %X\n", da2->ma); + + for (x = 0; x <= da2->hdisp; x += 8) /* hdisp = 1024 */ + { + uint8_t edat[8]; + uint8_t dat; + + /* get 8 pixels from vram */ + da2->ma &= da2->vram_display_mask; + *(uint32_t *) (&edat[0]) = *(uint32_t *) (&da2->vram[da2->ma << 3]); + *(uint32_t *) (&edat[4]) = *(uint32_t *) (&da2->vram[(da2->ma << 3) + 4]); + da2->ma += 1; + + dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)) | ((edat[4] >> 3) & (1 << 4)) | ((edat[5] >> 2) & (1 << 5)) | ((edat[6] >> 1) & (1 << 6)) | ((edat[7] >> 0) & (1 << 7)); + p[0] = da2->pallook[dat]; + dat = ((edat[0] >> 6) & (1 << 0)) | ((edat[1] >> 5) & (1 << 1)) | ((edat[2] >> 4) & (1 << 2)) | ((edat[3] >> 3) & (1 << 3)) | ((edat[4] >> 2) & (1 << 4)) | ((edat[5] >> 1) & (1 << 5)) | ((edat[6] >> 0) & (1 << 6)) | ((edat[7] << 1) & (1 << 7)); + p[1] = da2->pallook[dat]; + dat = ((edat[0] >> 5) & (1 << 0)) | ((edat[1] >> 4) & (1 << 1)) | ((edat[2] >> 3) & (1 << 2)) | ((edat[3] >> 2) & (1 << 3)) | ((edat[4] >> 1) & (1 << 4)) | ((edat[5] >> 0) & (1 << 5)) | ((edat[6] << 1) & (1 << 6)) | ((edat[7] << 2) & (1 << 7)); + p[2] = da2->pallook[dat]; + dat = ((edat[0] >> 4) & (1 << 0)) | ((edat[1] >> 3) & (1 << 1)) | ((edat[2] >> 2) & (1 << 2)) | ((edat[3] >> 1) & (1 << 3)) | ((edat[4] >> 0) & (1 << 4)) | ((edat[5] << 1) & (1 << 5)) | ((edat[6] << 2) & (1 << 6)) | ((edat[7] << 3) & (1 << 7)); + p[3] = da2->pallook[dat]; + dat = ((edat[0] >> 3) & (1 << 0)) | ((edat[1] >> 2) & (1 << 1)) | ((edat[2] >> 1) & (1 << 2)) | ((edat[3] >> 0) & (1 << 3)) | ((edat[4] << 1) & (1 << 4)) | ((edat[5] << 2) & (1 << 5)) | ((edat[6] << 3) & (1 << 6)) | ((edat[7] << 4) & (1 << 7)); + p[4] = da2->pallook[dat]; + dat = ((edat[0] >> 2) & (1 << 0)) | ((edat[1] >> 1) & (1 << 1)) | ((edat[2] >> 0) & (1 << 2)) | ((edat[3] << 1) & (1 << 3)) | ((edat[4] << 2) & (1 << 4)) | ((edat[5] << 3) & (1 << 5)) | ((edat[6] << 4) & (1 << 6)) | ((edat[7] << 5) & (1 << 7)); + p[5] = da2->pallook[dat]; + dat = ((edat[0] >> 1) & (1 << 0)) | ((edat[1] >> 0) & (1 << 1)) | ((edat[2] << 1) & (1 << 2)) | ((edat[3] << 2) & (1 << 3)) | ((edat[4] << 3) & (1 << 4)) | ((edat[5] << 4) & (1 << 5)) | ((edat[6] << 5) & (1 << 6)) | ((edat[7] << 6) & (1 << 7)); + p[6] = da2->pallook[dat]; + dat = ((edat[0] >> 0) & (1 << 0)) | ((edat[1] << 1) & (1 << 1)) | ((edat[2] << 2) & (1 << 2)) | ((edat[3] << 3) & (1 << 3)) | ((edat[4] << 4) & (1 << 4)) | ((edat[5] << 5) & (1 << 5)) | ((edat[6] << 6) & (1 << 6)) | ((edat[7] << 7) & (1 << 7)); + p[7] = da2->pallook[dat]; + p += 8; + } + // da2->writelines++; + } +} + +void +da2_updatevidselector(da2_t *da2) +{ da2_log("DA2 selector: %d\n", da2->ioctl[LS_MODE]); - if (da2->ioctl[LS_MODE] & 0x02) - { + if (da2->ioctl[LS_MODE] & 0x02) { + /* VGA passthrough mode */ da2->override = 1; svga_set_override(da2->mb_vga, 0); - } - else - { + } else { svga_set_override(da2->mb_vga, 1); da2->override = 0; } } -void da2_recalctimings(da2_t* da2) +void +da2_recalctimings(da2_t *da2) { double crtcconst; double _dispontime, _dispofftime, disptime; - da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff;//w - da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff;//w - da2->vsyncstart = da2->crtc[LC_VERTICAL_SYNC_START] & 0xfff;//w - da2->split = da2->crtc[LC_LINE_COMPAREJ] & 0xfff;//w Line Compare - da2->split = 0xfff; - da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff;//w - da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; + da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff; + da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff; + da2->vsyncstart = da2->crtc[LC_VERTICAL_SYNC_START] & 0xfff; + da2->split = da2->crtc[LC_LINE_COMPAREJ] & 0xfff; + da2->split = 0xfff; + da2->vblankstart = da2->crtc[LC_START_VERTICAL_BLANK] & 0xfff; + da2->hdisp = da2->crtc[LC_H_DISPLAY_ENABLE_END]; if (da2->crtc[LC_START_H_DISPLAY_ENAB] & 1) { da2->hdisp--; da2->dispend -= 29; - } - else { - //da2->vtotal += 2; + } else { + // da2->vtotal += 2; da2->dispend--; - //da2->vsyncstart++; - //da2->split++; - //da2->vblankstart++; - //da2->hdisp--; + // da2->vsyncstart++; + // da2->split++; + // da2->vblankstart++; + // da2->hdisp--; } da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; da2->htotal += 1; - da2->rowoffset = da2->crtc[LC_OFFSET];/* number of bytes in a scanline */ + da2->rowoffset = da2->crtc[LC_OFFSET]; /* number of bytes in a scanline */ da2->clock = da2->da2const; - //da2->lowres = da2->attrc[LV_MODE_CONTROL] & 0x40; + // da2->lowres = da2->attrc[LV_MODE_CONTROL] & 0x40; - //da2->interlace = 0; + // da2->interlace = 0; - //da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b + // da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b da2->ca_adj = 0; da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE]; da2->hdisp_time = da2->hdisp; - da2->render = da2_render_blank; + da2->render = da2_render_blank; /* determine display mode */ - //if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) - if (da2->attrc[LV_COMPATIBILITY] & 0x08) - { + // if (da2->attr_palette_enable && (da2->attrc[0x1f] & 0x08)) + if (da2->attrc[LV_COMPATIBILITY] & 0x08) { /* 16 color graphics mode */ if (!(da2->ioctl[LS_MODE] & 0x01)) { da2->hdisp *= 16; da2->char_width = 13; - da2->hdisp_old = da2->hdisp; + da2->hdisp_old = da2->hdisp; if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) { da2_log("Set videomode to PS/55 8 bpp graphics.\n"); - da2->render = da2_render_color_8bpp; + da2->render = da2_render_color_8bpp; da2->vram_display_mask = DA2_MASK_GRAM; - } - else {/* PS/55 8-color */ + } else { /* PS/55 8-color */ da2_log("Set videomode to PS/55 4 bpp graphics.\n"); da2->vram_display_mask = DA2_MASK_GRAM; - da2->render = da2_render_color_4bpp; + da2->render = da2_render_color_4bpp; } - } - else { + } else { /* text mode */ if (da2->attrc[LV_ATTRIBUTE_CNTL] & 1) { da2_log("Set videomode to PS/55 Mode 03 text.\n"); - da2->render = da2_render_textm3; + da2->render = da2_render_textm3; da2->vram_display_mask = DA2_MASK_CRAM; } /* PS/55 text(color/mono) */ else { da2_log("Set videomode to PS/55 Mode 8/E text.\n"); - da2->render = da2_render_text; + da2->render = da2_render_text; da2->vram_display_mask = DA2_MASK_CRAM; } da2->hdisp *= 13; - da2->hdisp_old = da2->hdisp; + da2->hdisp_old = da2->hdisp; da2->char_width = 13; } - } - else - { + } else { da2_log("Set videomode to blank.\n"); } - //if (!da2->scrblank && da2->attr_palette_enable) + // if (!da2->scrblank && da2->attr_palette_enable) //{ - //da2->render = da2_draw_text; + // da2->render = da2_draw_text; //} - //da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); + // da2_log("da2_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", da2_render, da2_render_text_40, da2_render_text_80, da2_render_8bpp_lowres, da2_render_8bpp_highres, da2_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8); - //if (da2->recalctimings_ex) - // da2->recalctimings_ex(da2); + // if (da2->recalctimings_ex) + // da2->recalctimings_ex(da2); if (da2->vblankstart < da2->dispend) da2->dispend = da2->vblankstart; crtcconst = da2->clock * da2->char_width; - disptime = da2->htotal; + disptime = da2->htotal; _dispontime = da2->hdisp_time; da2_log("Disptime %f dispontime %f hdisp %i\n", disptime, _dispontime, da2->hdisp); - //if (da2->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; } + // if (da2->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; } _dispofftime = disptime - _dispontime; _dispontime *= crtcconst; _dispofftime *= crtcconst; - da2->dispontime = (uint64_t)_dispontime; - da2->dispofftime = (uint64_t)_dispofftime; + da2->dispontime = (uint64_t) _dispontime; + da2->dispofftime = (uint64_t) _dispofftime; if (da2->dispontime < TIMER_USEC) da2->dispontime = TIMER_USEC; if (da2->dispofftime < TIMER_USEC) da2->dispofftime = TIMER_USEC; - da2_log("da2 horiz total %i display end %i vidclock %f\n",da2->crtc[0],da2->crtc[1],da2->clock); - //da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart); - //da2_log("total %f on %i cycles off %i cycles frame %i sec %i\n",disptime*crtcconst,da2->dispontime,da2->dispofftime,(da2->dispontime+da2->dispofftime)*da2->vtotal,(da2->dispontime+da2->dispofftime)*da2->vtotal*70); + da2_log("da2 horiz total %i display end %i vidclock %f\n", da2->crtc[0], da2->crtc[1], da2->clock); + // da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart); + // da2_log("total %f on %i cycles off %i cycles frame %i sec %i\n",disptime*crtcconst,da2->dispontime,da2->dispofftime,(da2->dispontime+da2->dispofftime)*da2->vtotal,(da2->dispontime+da2->dispofftime)*da2->vtotal*70); - //da2_log("da2->render %08X\n", da2->render); + // da2_log("da2->render %08X\n", da2->render); } -uint8_t da2_mca_read(int port, void *p) +static void +da2_mapping_update(da2_t *da2) { - da2_t *da2 = (da2_t *)p; - return da2->pos_regs[port & 7]; + /* Has the CardEnable bit been changed? */ + if (!((da2->pos_regs[2] ^ da2->old_pos2) & 1)) + return; + da2->old_pos2 = da2->pos_regs[2]; + // da2_recalc_mapping(da2); + if (da2->pos_regs[2] & 0x01) { + da2_log("DA2 enable registers\n"); + for (int i = 0; i < 8; i++) + da2_log("DA2 POS[%d]: %x\n", i, da2->pos_regs[i]); + io_sethandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_sethandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_sethandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); + mem_mapping_enable(&da2->cmapping); + mem_mapping_enable(&da2->mmio.mapping); + timer_enable(&da2->timer); + } else { + da2_log("DA2 disable registers\n"); + timer_disable(&da2->timer); + mem_mapping_disable(&da2->cmapping); + mem_mapping_disable(&da2->mmio.mapping); + io_removehandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_removehandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); + io_removehandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); + } } -static void da2_mapping_update(da2_t *da2) +uint8_t +da2_mca_read(int port, void *p) { - if (!((da2->pos_regs[2] ^ da2->old_pos2) & 1)) return; - da2->old_pos2 = da2->pos_regs[2]; - //da2_recalc_mapping(da2); - if (da2->pos_regs[2] & 0x01) - { - da2_log("DA2 enable registers\n"); - for (int i = 0; i < 8; i++) - da2_log("DA2 POS[%d]: %x\n", i, da2->pos_regs[i]); - io_sethandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); - io_sethandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); - io_sethandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); - mem_mapping_enable(&da2->cmapping); - mem_mapping_enable(&da2->mmio.mapping); - timer_enable(&da2->timer); - } - else - { - da2_log("DA2 disable registers\n"); - timer_disable(&da2->timer); - mem_mapping_disable(&da2->cmapping); - mem_mapping_disable(&da2->mmio.mapping); - io_removehandler(0x03c0, 0x000a, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); - io_removehandler(0x03e0, 0x0010, da2_inb, da2_inw, NULL, da2_outb, da2_outw, NULL, da2); - io_removehandler(0x03d0, 0x000b, da2_in_ISR, NULL, NULL, da2_out_ISR, NULL, NULL, da2); - } + da2_t *da2 = (da2_t *) p; + return da2->pos_regs[port & 7]; } -void da2_mca_write(int port, uint8_t val, void *p) +void +da2_mca_write(int port, uint8_t val, void *p) { - da2_t *da2 = (da2_t *)p; + da2_t *da2 = (da2_t *) p; - da2_log("da2_mca_write: port=%04x val=%02x\n", port, val); - - if (port < 0x102) - return; - da2->pos_regs[port & 7] = val; + da2_log("da2_mca_write: port=%04x val=%02x\n", port, val); - da2_mapping_update(da2); + if (port < 0x102) + return; + da2->pos_regs[port & 7] = val; + + da2_mapping_update(da2); } -static uint8_t da2_mca_feedb(void* priv) +static uint8_t +da2_mca_feedb(void *priv) { - const da2_t* da2 = (da2_t*)priv; + const da2_t *da2 = (da2_t *) priv; - return da2->pos_regs[2] & 0x01; + return da2->pos_regs[2] & 0x01; } -static void da2_mca_reset(void *p) +static void +da2_mca_reset(void *p) { - da2_t *da2 = (da2_t *)p; - da2_reset(da2); - da2_mca_write(0x102, 0, da2); + da2_t *da2 = (da2_t *) p; + da2_log("da2_mca_reset called.\n"); + da2_reset(da2); + da2_mca_write(0x102, 0, da2); } -static void da2_gdcropB(uint32_t addr, da2_t* da2) { +static void +da2_gdcropB(uint32_t addr, da2_t *da2) +{ for (int i = 0; i < 8; i++) { if (da2->writemask & (1 << i)) { - //da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW]); - switch (da2->gdcreg[LG_COMMAND] & 0x03) - { - case 0: /*Set*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - case 1: /*AND*/ - //da2->vram[addr | i] = (da2->gdcinput[i] | ~da2->gdcreg[LG_BIT_MASK_LOW]) & da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - case 2: /*OR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; - case 3: /*XOR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) ^ da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - break; + // da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW]); + switch (da2->gdcreg[LG_COMMAND] & 0x03) { + case 0: /*Set*/ + // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 1: /*AND*/ + // da2->vram[addr | i] = (da2->gdcinput[i] | ~da2->gdcreg[LG_BIT_MASK_LOW]) & da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 2: /*OR*/ + // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; + case 3: /*XOR*/ + // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) ^ da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + break; } } } } -static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t* da2) { +static void +da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t *da2) +{ uint8_t bitmask_l = bitmask & 0xff; uint8_t bitmask_h = bitmask >> 8; for (int i = 0; i < 8; i++) { if (da2->writemask & (1 << i)) { - //da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]); - switch (da2->gdcreg[LG_COMMAND] & 0x03) - { - case 0: /*Set*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l); - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h); - da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - case 1: /*AND*/ - //da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i]; - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - case 2: /*OR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i]; - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; - case 3: /*XOR*/ - //da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i]; - //da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); - break; + // da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]); + switch (da2->gdcreg[LG_COMMAND] & 0x03) { + case 0: /*Set*/ + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l); + // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h); + da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 1: /*AND*/ + // da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i]; + // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 2: /*OR*/ + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i]; + // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; + case 3: /*XOR*/ + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i]; + // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8); + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); + da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h); + break; } } } } -static uint8_t da2_mmio_read(uint32_t addr, void* p) +static uint8_t +da2_mmio_read(uint32_t addr, void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; addr &= DA2_MASK_MMIO; if (da2->ioctl[LS_MMIO] & 0x10) { if (da2->fctl[LF_MMIO_SEL] == 0x80) /* linear access */ - addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17); - else - { + addr |= ((uint32_t) da2->fctl[LF_MMIO_ADDR] << 17); + else { /* 64k bank switch access */ uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; index <<= 8; index |= da2->fctl[LF_MMIO_ADDR]; addr += index * 0x40; } - //da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + // da2_log("PS55_MemHnd: Read from mem %x, bank %x, addr %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); switch (da2->fctl[LF_MMIO_MODE] & 0xf0) { - case 0xb0:/* Gaiji RAM */ - addr &= DA2_MASK_GAIJIRAM;/* safety access */ - //da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]); - return da2->mmio.ram[addr]; - break; - case 0x10:/* Font ROM */ - if (da2->mmio.charset == DA2_DCONFIG_CHARSET_HANT) { - if (addr >= 0x1a0000) return DA2_INVALIDACCESS8; - if (addr >= 0x180000) addr -= 0x40000; /* The bank 12 (180000h-19ffffh) is beyond the available ROM address range, - but the Chinese font sub card actually has this alias, and is used by DOS T5.0. */ - } - if (addr >= DA2_FONTROM_SIZE) return DA2_INVALIDACCESS8; - //da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); - return da2->mmio.font[addr]; - break; - default: - return DA2_INVALIDACCESS8;/* invalid memory access */ - break; + case 0xb0: /* Gaiji RAM */ + addr &= DA2_MASK_GAIJIRAM; /* safety access */ + // da2_log("PS55_MemHnd_G: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 128, addr, da2->mmio.font[addr]); + return da2->mmio.ram[addr]; + break; + case 0x10: /* Font ROM */ + if (da2->mmio.charset == DA2_DCONFIG_CHARSET_HANT) { + if (addr >= 0x1a0000) + return DA2_INVALIDACCESS8; + if (addr >= 0x180000) + addr -= 0x40000; /* The bank 12 (180000h-19ffffh) is beyond the available ROM address range, + but the Chinese font sub card actually has this alias, and is used by DOS T5.0. */ + } + if (addr >= DA2_FONTROM_SIZE) + return DA2_INVALIDACCESS8; + // da2_log("PS55_MemHnd: Read from mem %x, bank %x, chr %x (%x), val %x\n", da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr / 72, addr, da2->mmio.font[addr]); + return da2->mmio.font[addr]; + break; + default: + return DA2_INVALIDACCESS8; /* invalid memory access */ + break; } - } - else if (!(da2->ioctl[LS_MODE] & 1))/* 8 or 256 color mode */ + } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 or 256 color mode */ { cycles -= video_timing_read_b; for (int i = 0; i < 8; i++) - da2->gdcla[i] = da2->vram[(addr << 3) | i];/* read in byte */ - //da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); - if (da2->gdcreg[LG_MODE] & 0x08) {/* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ + da2->gdcla[i] = da2->vram[(addr << 3) | i]; /* read in byte */ + // da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); + if (da2->gdcreg[LG_MODE] & 0x08) { /* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint8_t ret = 0; - for (int i = 0; i < 8; i++) - { - if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))/* color don't care register */ + for (int i = 0; i < 8; i++) { + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i)) /* color don't care register */ ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xff : 0); } return ~ret; - } - else return da2->gdcla[da2->readplane]; - } - else /* text mode 3 */ + } else + return da2->gdcla[da2->readplane]; + } else /* text mode 3 */ { cycles -= video_timing_read_b; return da2->vram[addr]; } } -static uint16_t da2_mmio_readw(uint32_t addr, void* p) +static uint16_t +da2_mmio_readw(uint32_t addr, void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); if (da2->ioctl[LS_MMIO] & 0x10) { - return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); - } - else if (!(da2->ioctl[LS_MODE] & 1))/* 8 color or 256 color mode */ + return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); + } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 color or 256 color mode */ { cycles -= video_timing_read_w; addr &= DA2_MASK_MMIO; for (int i = 0; i < 8; i++) - da2->gdcla[i] = (uint16_t)(da2->vram[(addr << 3) | i]) | ((uint16_t)(da2->vram[((addr << 3) + 8) | i]) << 8);/* read vram into latch */ + da2->gdcla[i] = (uint16_t) (da2->vram[(addr << 3) | i]) | ((uint16_t) (da2->vram[((addr << 3) + 8) | i]) << 8); /* read vram into latch */ #ifdef ENABLE_DA2_DEBUGBLT ////debug - //if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) + // if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) //{ - // fprintf(da2->mmrdbg_fp, "\nR %x ", addr); - // for (int i = 0; i <= 0xb; i++) - // fprintf(da2->mmrdbg_fp, "%02x ", da2->gdcreg[i]); - //} - //for (int i = 0; i < 16; i++) + // fprintf(da2->mmrdbg_fp, "\nR %x ", addr); + // for (int i = 0; i <= 0xb; i++) + // fprintf(da2->mmrdbg_fp, "%02x ", da2->gdcreg[i]); + // } + // for (int i = 0; i < 16; i++) //{ - // int pixeldata = 0; - // if (da2->gdcla[da2->readplane] & (1 << (15 - i))) pixeldata = 1; - // fprintf(da2->mmrdbg_fp, "%X", pixeldata); - //} - //da2->mmrdbg_vidaddr = addr; + // int pixeldata = 0; + // if (da2->gdcla[da2->readplane] & (1 << (15 - i))) pixeldata = 1; + // fprintf(da2->mmrdbg_fp, "%X", pixeldata); + // } + // da2->mmrdbg_vidaddr = addr; #endif - if (da2->gdcreg[LG_MODE] & 0x08) {/* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ + if (da2->gdcreg[LG_MODE] & 0x08) { /* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint16_t ret = 0; - for (int i = 0; i < 8; i++) - { - if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i))/* color don't care register */ + for (int i = 0; i < 8; i++) { + if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i)) /* color don't care register */ ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xffff : 0); } return ~ret; - } - else - { - //da2_log("da2_Rw: %05x=%04x\n", addr, da2->gdcla[da2->readplane]); + } else { + // da2_log("da2_Rw: %05x=%04x\n", addr, da2->gdcla[da2->readplane]); return da2->gdcla[da2->readplane]; } - } - else { - return (uint16_t)da2_mmio_read(addr, da2) | (uint16_t)(da2_mmio_read(addr + 1, da2) << 8); + } else { + return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); } } -static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) +static void +da2_mmio_write(uint32_t addr, uint8_t val, void *p) { - da2_t* da2 = (da2_t*)p; - //da2_log("da2_mmio_write %x %x\n", addr, val); - if ((addr & ~DA2_MASK_MMIO) != 0xA0000) return; + da2_t *da2 = (da2_t *) p; + // da2_log("da2_mmio_write %x %x\n", addr, val); + if ((addr & ~DA2_MASK_MMIO) != 0xA0000) + return; addr &= DA2_MASK_MMIO; if (da2->ioctl[LS_MMIO] & 0x10) { - //if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI); + // if(da2->ioctl[LS_MMIO] == 0x1f) da2_log("mw mem %x, addr %x, val %x, ESDI %x:%x DSSI %x:%x\n", da2->fctl[LF_MMIO_MODE], addr, val, ES, DI, DS, SI); /* Gaiji RAM */ if (da2->fctl[LF_MMIO_SEL] == 0x80) - addr |= ((uint32_t)da2->fctl[LF_MMIO_ADDR] << 17);/* xxxy yyyy yyyy yyyy yyyy */ - else - { + addr |= ((uint32_t) da2->fctl[LF_MMIO_ADDR] << 17); /* xxxy yyyy yyyy yyyy yyyy */ + else { uint32_t index = da2->fctl[LF_MMIO_MODE] & 0x0f; index <<= 8; index |= da2->fctl[LF_MMIO_ADDR]; addr += index * 0x40; } switch (da2->fctl[LF_MMIO_MODE]) { - case 0xb0:/* Gaiji RAM 1011 0000 */ - addr &= DA2_MASK_GAIJIRAM;/* safety access */ - da2->mmio.ram[addr] = val; - break; - case 0x10:/* Font ROM 0001 0000 */ - /* Read-Only */ - break; - case 0x00: - //da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - //addr &= 0x7f;/* OS/2 write addr 1cf80-1cfc3, val xx */ - //if (addr >= DA2_BLT_MEMSIZE) - //{ - // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - // return; - //} - da2->bitblt.indata = 1; - if(da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) - da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - da2->bitblt.payload[da2->bitblt.payload_addr] = val; - da2->bitblt.payload_addr++; - break; - default: - da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - break; + case 0xb0: /* Gaiji RAM 1011 0000 */ + addr &= DA2_MASK_GAIJIRAM; /* safety access */ + da2->mmio.ram[addr] = val; + break; + case 0x10: /* Font ROM 0001 0000 */ + /* Read-Only */ + break; + case 0x00: + // da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); + // addr &= 0x7f;/* OS/2 write addr 1cf80-1cfc3, val xx */ + // if (addr >= DA2_BLT_MEMSIZE) + //{ + // da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + // return; + // } + da2->bitblt.indata = 1; + if (da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) + da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_addr++; + break; + default: + da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); + break; } - } - else if (!(da2->ioctl[LS_MODE] & 1))/* 8 color or 256 color mode */ + } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 color or 256 color mode */ { uint8_t wm = da2->writemask; - //da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); + // da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); #ifdef ENABLE_DA2_DEBUGBLT - //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + // if (!(da2->gdcreg[LG_COMMAND] & 0x08)) //{ - if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) - { + if (((int) addr - (int) da2->mmdbg_vidaddr) > 2 || (((int) da2->mmdbg_vidaddr - (int) addr) > 2) || da2->mmdbg_vidaddr == addr) { fprintf(da2->mmdbg_fp, "\nB %x ", addr); for (int i = 0; i <= 0xb; i++) fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); } - for (int i = 0; i < 8; i++) - { + for (int i = 0; i < 8; i++) { int pixeldata = 0; - if (val & (1 << (7 - i))) pixeldata = (da2->writemask & 0xf); + if (val & (1 << (7 - i))) + pixeldata = (da2->writemask & 0xf); fprintf(da2->mmdbg_fp, "%X", pixeldata); } da2->mmdbg_vidaddr = addr; @@ -2458,270 +2447,270 @@ static void da2_mmio_write(uint32_t addr, uint8_t val, void* p) addr <<= 3; for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];/* use latch */ + da2->gdcsrc[i] = da2->gdcla[i]; /* use latch */ - //da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); - //da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); + // da2_log("da2_Wb m%02x r%02x %05x:%02x %x:%x\n", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, cs >> 4, cpu_state.pc); + // da2_log("da2_Wb m%02x r%02x %05x:%02x=%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); - if (!(da2->gdcreg[LG_COMMAND] & 0x08)) - { + if (!(da2->gdcreg[LG_COMMAND] & 0x08)) { for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; - else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; - else da2->gdcinput[i] = val; + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) + da2->gdcinput[i] = ~val; + else + da2->gdcinput[i] = val; da2_gdcropB(addr, da2); return; } - switch (da2->writemode) - { - case 2: - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) da2->vram[addr | i] = da2->gdcsrc[i]; - break; - case 0: - if (da2->gdcreg[LG_DATA_ROTATION] & 7) - val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - if (da2->gdcreg[LG_BIT_MASK_LOW] == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { + switch (da2->writemode) { + case 2: for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) da2->vram[addr | i] = val; - } - else - { - for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; - else da2->gdcinput[i] = val; + if (da2->writemask & (1 << i)) + da2->vram[addr | i] = da2->gdcsrc[i]; + break; + case 0: + if (da2->gdcreg[LG_DATA_ROTATION] & 7) + val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; + if (da2->gdcreg[LG_BIT_MASK_LOW] == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + da2->vram[addr | i] = val; + } else { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + else + da2->gdcinput[i] = val; + + for (int i = 0; i < 8; i++) + da2->debug_vramold[i] = da2->vram[addr | i]; /* use latch */ + da2_gdcropB(addr, da2); + // for (int i = 0; i < 8; i++) + // da2_log("\tsrc %02x in %02x bitm %02x mod %x rop %x: %02x -> %02x\n", da2->gdcsrc[i], da2->gdcinput[i], da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch + ////da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); + } + break; + case 1: + if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) + da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + } else { + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); + da2_gdcropB(addr, da2); + } + break; + case 3: + if (da2->gdcreg[LG_DATA_ROTATION] & 7) + val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; + wm = da2->gdcreg[LG_BIT_MASK_LOW]; + da2->gdcreg[LG_BIT_MASK_LOW] &= val; for (int i = 0; i < 8; i++) - da2->debug_vramold[i] = da2->vram[addr | i];/* use latch */ + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; da2_gdcropB(addr, da2); - //for (int i = 0; i < 8; i++) - // da2_log("\tsrc %02x in %02x bitm %02x mod %x rop %x: %02x -> %02x\n", da2->gdcsrc[i], da2->gdcinput[i], da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch - ////da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); - } - break; - case 1: - if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - } - else - { - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); - da2_gdcropB(addr, da2); - } - break; - case 3: - if (da2->gdcreg[LG_DATA_ROTATION] & 7) - val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - wm = da2->gdcreg[LG_BIT_MASK_LOW]; - da2->gdcreg[LG_BIT_MASK_LOW] &= val; - - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; - da2_gdcropB(addr, da2); - da2->gdcreg[LG_BIT_MASK_LOW] = wm; - break; + da2->gdcreg[LG_BIT_MASK_LOW] = wm; + break; } - //da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); - } - else/* mode 3h text */ + // da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); + } else /* mode 3h text */ { cycles -= video_timing_write_b; da2->vram[addr] = val; da2->fullchange = 2; } } -uint16_t rightRotate(uint16_t data, uint8_t count) +uint16_t +rightRotate(uint16_t data, uint8_t count) { return (data >> count) | (data << (sizeof(data) * 8 - count)); } -static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void* p) +static void +da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) { - da2_t* da2 = (da2_t*)p; - uint8_t wm = da2->writemask; + da2_t *da2 = (da2_t *) p; + uint8_t wm = da2->writemask; uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; bitmask <<= 8; - bitmask |= (uint16_t)da2->gdcreg[LG_BIT_MASK_LOW]; + bitmask |= (uint16_t) da2->gdcreg[LG_BIT_MASK_LOW]; #ifdef ENABLE_DA2_DEBUGBLT - //if (!(da2->gdcreg[LG_COMMAND] & 0x08)) + // if (!(da2->gdcreg[LG_COMMAND] & 0x08)) //{ - if (((int)addr - (int)da2->mmdbg_vidaddr) > 2 || (((int)da2->mmdbg_vidaddr - (int)addr) > 2) || da2->mmdbg_vidaddr == addr) - { - fprintf(da2->mmdbg_fp, "\nW %x ", addr); - for (int i = 0; i <= 0xb; i++) - fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); - } - for (int i = 0; i < 16; i++) - { - int pixeldata = 0; - if (val & (1 << (15 - i))) pixeldata = (da2->writemask & 0xf); - fprintf(da2->mmdbg_fp, "%X", pixeldata); - } - da2->mmdbg_vidaddr = addr; + if (((int) addr - (int) da2->mmdbg_vidaddr) > 2 || (((int) da2->mmdbg_vidaddr - (int) addr) > 2) || da2->mmdbg_vidaddr == addr) { + fprintf(da2->mmdbg_fp, "\nW %x ", addr); + for (int i = 0; i <= 0xb; i++) + fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); + } + for (int i = 0; i < 16; i++) { + int pixeldata = 0; + if (val & (1 << (15 - i))) + pixeldata = (da2->writemask & 0xf); + fprintf(da2->mmdbg_fp, "%X", pixeldata); + } + da2->mmdbg_vidaddr = addr; //} #endif cycles -= video_timing_write_w; - //cycles_lost += video_timing_write_w; + // cycles_lost += video_timing_write_w; - //da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); - //da2_log("da2_gcW %05X %02X %04X:%04X esdi %04X:%04X dssi %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); + // da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); + // da2_log("da2_gcW %05X %02X %04X:%04X esdi %04X:%04X dssi %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); - da2->changedvram[addr >> 12] = changeframecount; + da2->changedvram[addr >> 12] = changeframecount; da2->changedvram[(addr + 1) >> 12] = changeframecount; addr <<= 3; for (int i = 0; i < 8; i++) - da2->gdcsrc[i] = da2->gdcla[i];/* use latch */ + da2->gdcsrc[i] = da2->gdcla[i]; /* use latch */ - if (!(da2->gdcreg[LG_COMMAND] & 0x08)) - { + if (!(da2->gdcreg[LG_COMMAND] & 0x08)) { for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; - else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) da2->gdcinput[i] = ~val; - else da2->gdcinput[i] = val; + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + else if (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) + da2->gdcinput[i] = ~val; + else + da2->gdcinput[i] = val; da2_gdcropW(addr, bitmask, da2); return; } - //da2_log("da2_Ww m%02x r%02x %05x:%04x=%02x%02x%02x%02x,%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] - // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); - switch (da2->writemode) - { - case 2: - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) - { - da2->vram[addr | i] = da2->gdcsrc[i] & 0xff; - da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; + // da2_log("da2_Ww m%02x r%02x %05x:%04x=%02x%02x%02x%02x,%02x%02x%02x%02x->", da2->gdcreg[0x5], da2->gdcreg[LG_COMMAND], addr >> 3, val, da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] + // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); + switch (da2->writemode) { + case 2: + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) { + da2->vram[addr | i] = da2->gdcsrc[i] & 0xff; + da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; + } + break; + case 0: + if (da2->gdcreg[LG_DATA_ROTATION] & 15) + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work + if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) { + da2->vram[addr | i] = val & 0xff; + da2->vram[(addr + 8) | i] = val >> 8; + } + } else { + for (int i = 0; i < 8; i++) + if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + else + da2->gdcinput[i] = val; + da2_gdcropW(addr, bitmask, da2); + // da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); } - break; - case 0: - if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work - if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) - { - da2->vram[addr | i] = val & 0xff; - da2->vram[(addr + 8) | i] = val >> 8; - } - } - else - { - for (int i = 0; i < 8; i++) - if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; - else da2->gdcinput[i] = val; - da2_gdcropW(addr, bitmask, da2); - //da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); - } - break; - case 1: - if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) - { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) - { - uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); - da2->vram[addr | i] = wdata & 0xff; - da2->vram[(addr + 8) | i] = wdata >> 8; - } - } - else - { - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); - da2_gdcropW(addr, bitmask, da2); - } - break; - case 3: - if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15);//val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work - wm = bitmask; - bitmask &= val; + break; + case 1: + if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { + for (int i = 0; i < 8; i++) + if (da2->writemask & (1 << i)) { + uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + da2->vram[addr | i] = wdata & 0xff; + da2->vram[(addr + 8) | i] = wdata >> 8; + } + } else { + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); + da2_gdcropW(addr, bitmask, da2); + } + break; + case 3: + if (da2->gdcreg[LG_DATA_ROTATION] & 15) + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work + wm = bitmask; + bitmask &= val; - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; - da2_gdcropW(addr, bitmask, da2); - bitmask = wm; - break; + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + da2_gdcropW(addr, bitmask, da2); + bitmask = wm; + break; } - //da2_log("%02x%02x%02x%02x,%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] - // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); + // da2_log("%02x%02x%02x%02x,%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] + // , da2->vram[addr + 8], da2->vram[addr + 9], da2->vram[addr + 10], da2->vram[addr + 11]); } -static void da2_mmio_writew(uint32_t addr, uint16_t val, void* p) +static void +da2_mmio_writew(uint32_t addr, uint16_t val, void *p) { - da2_t* da2 = (da2_t*)p; - //if ((addr & ~0x1ffff) != 0xA0000) return; + da2_t *da2 = (da2_t *) p; + // if ((addr & ~0x1ffff) != 0xA0000) return; if (da2->ioctl[LS_MMIO] & 0x10) { - //da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + // da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); - } - else if (!(da2->ioctl[LS_MODE] & 1))/* 8 color or 256 color mode */ + } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 color or 256 color mode */ { addr &= DA2_MASK_MMIO; - //return; - //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + // return; + // da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_gc_writeW(addr, val, da2); - } - else {/* mode 3h text */ - //if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); - //da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); + } else { /* mode 3h text */ + // if (addr & 0xff00 == 0) da2_log("da2_mmio_write %x %x %04X:%04X\n", addr, val, CS, cpu_state.pc); + // da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); } } -static void da2_code_write(uint32_t addr, uint8_t val, void* p) +static void +da2_code_write(uint32_t addr, uint8_t val, void *p) { - da2_t* da2 = (da2_t*)p; - //if ((addr & ~0xfff) != 0xE0000) return; + da2_t *da2 = (da2_t *) p; + // if ((addr & ~0xfff) != 0xE0000) return; addr &= DA2_MASK_CRAM; da2->cram[addr] = val; da2->fullchange = 2; } -static void da2_code_writeb(uint32_t addr, uint8_t val, void* p) +static void +da2_code_writeb(uint32_t addr, uint8_t val, void *p) { - da2_t* da2 = (da2_t*)p; - //da2_log("DA2_code_writeb: Write to %x, val %x\n", addr, val); + da2_t *da2 = (da2_t *) p; + // da2_log("DA2_code_writeb: Write to %x, val %x\n", addr, val); cycles -= video_timing_write_b; da2_code_write(addr, val, da2); } -static void da2_code_writew(uint32_t addr, uint16_t val, void* p) +static void +da2_code_writew(uint32_t addr, uint16_t val, void *p) { - //da2_log("DA2_code_writew: Write to %x, val %x\n", addr, val); - da2_t* da2 = (da2_t*)p; + // da2_log("DA2_code_writew: Write to %x, val %x\n", addr, val); + da2_t *da2 = (da2_t *) p; cycles -= video_timing_write_w; da2_code_write(addr, val & 0xff, da2); da2_code_write(addr + 1, val >> 8, da2); } -static uint8_t da2_code_read(uint32_t addr, void* p) +static uint8_t +da2_code_read(uint32_t addr, void *p) { - da2_t* da2 = (da2_t*)p; - if ((addr & ~DA2_MASK_CRAM) != 0xE0000) return DA2_INVALIDACCESS8; + da2_t *da2 = (da2_t *) p; + if ((addr & ~DA2_MASK_CRAM) != 0xE0000) + return DA2_INVALIDACCESS8; addr &= DA2_MASK_CRAM; return da2->cram[addr]; } -static uint8_t da2_code_readb(uint32_t addr, void* p) +static uint8_t +da2_code_readb(uint32_t addr, void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; cycles -= video_timing_read_b; return da2_code_read(addr, da2); } -static uint16_t da2_code_readw(uint32_t addr, void* p) +static uint16_t +da2_code_readw(uint32_t addr, void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; cycles -= video_timing_read_w; return da2_code_read(addr, da2) | (da2_code_read(addr + 1, da2) << 8); - //return 0; } -void da2_doblit(int y1, int y2, int wx, int wy, da2_t* da2) +void +da2_doblit(int y1, int y2, int wx, int wy, da2_t *da2) { if (wx != xsize || wy != ysize) { xsize = wx; @@ -2736,28 +2725,26 @@ void da2_doblit(int y1, int y2, int wx, int wy, da2_t* da2) video_res_x = wx; video_res_y = wy; - video_bpp = 8; + video_bpp = 8; } -void da2_poll(void* priv) +void +da2_poll(void *priv) { - da2_t* da2 = (da2_t*)priv; - int x; + da2_t *da2 = (da2_t *) priv; + int x; - if (!da2->linepos) - { + if (!da2->linepos) { timer_advance_u64(&da2->timer, da2->dispofftime); - //if (output) printf("Display off %f\n",vidtime); + // if (output) printf("Display off %f\n",vidtime); da2->cgastat |= 1; da2->linepos = 1; - if (da2->dispon) - { + if (da2->dispon) { da2->hdisp_on = 1; da2->ma &= da2->vram_display_mask; - if (da2->firstline == 2000) - { + if (da2->firstline == 2000) { da2->firstline = da2->displine; video_wait_for_buffer(); } @@ -2769,27 +2756,24 @@ void da2_poll(void* priv) da2->lastline = da2->displine; } - //da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); + // da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask); da2->displine++; - //if (da2->interlace) - // da2->displine++; - if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) - { - //da2_log("Vsync off at line %i\n",displine); + // if (da2->interlace) + // da2->displine++; + if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) { + // da2_log("Vsync off at line %i\n",displine); da2->cgastat &= ~8; } da2->vslines++; if (da2->displine > 1200) da2->displine = 0; - //da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], - //displine, vc, ma); - } - else - { - //da2_log("VC %i ma %05X\n", da2->vc, da2->ma); + // da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322], + // displine, vc, ma); + } else { + // da2_log("VC %i ma %05X\n", da2->vc, da2->ma); timer_advance_u64(&da2->timer, da2->dispontime); - //if (output) printf("Display on %f\n",vidtime); + // if (output) printf("Display on %f\n",vidtime); if (da2->dispon) da2->cgastat &= ~1; da2->hdisp_on = 0; @@ -2797,21 +2781,17 @@ void da2_poll(void* priv) da2->linepos = 0; if (da2->sc == (da2->crtc[LC_CURSOR_ROW_END] & 31)) da2->con = 0; - if (da2->dispon) - { - if (da2->sc == da2->rowcount) - { + if (da2->dispon) { + if (da2->sc == da2->rowcount) { da2->linecountff = 0; - da2->sc = 0; + da2->sc = 0; - da2->maback += (da2->rowoffset << 1);/* color = 0x50(80), mono = 0x40(64) */ + da2->maback += (da2->rowoffset << 1); /* color = 0x50(80), mono = 0x40(64) */ if (da2->interlace) da2->maback += (da2->rowoffset << 1); da2->maback &= da2->vram_display_mask; da2->ma = da2->maback; - } - else - { + } else { da2->sc++; da2->sc &= 31; da2->ma = da2->maback; @@ -2821,46 +2801,40 @@ void da2_poll(void* priv) da2->vc++; da2->vc &= 2047; - if (da2->vc == da2->dispend) - { + if (da2->vc == da2->dispend) { da2->dispon = 0; - //if (da2->crtc[10] & 0x20) da2->cursoron = 0; - //else da2->cursoron = da2->blink & 16; - if (da2->ioctl[LS_MODE] & 1) {/* in text mode */ - if (da2->attrc[LV_CURSOR_CONTROL] & 0x01)/* cursor blinking */ + // if (da2->crtc[10] & 0x20) da2->cursoron = 0; + // else da2->cursoron = da2->blink & 16; + if (da2->ioctl[LS_MODE] & 1) { /* in text mode */ + if (da2->attrc[LV_CURSOR_CONTROL] & 0x01) /* cursor blinking */ { da2->cursoron = (da2->blink | 1) & da2->blinkconf; - } - else - { + } else { da2->cursoron = 0; } - if (!(da2->blink & (0x10 - 1)))/* force redrawing for cursor and blink attribute */ + if (!(da2->blink & (0x10 - 1))) /* force redrawing for cursor and blink attribute */ da2->fullchange = 2; } da2->blink++; - for (x = 0; x < ((da2->vram_mask + 1) >> 12); x++) - { + for (x = 0; x < ((da2->vram_mask + 1) >> 12); x++) { if (da2->changedvram[x]) da2->changedvram[x]--; } - //memset(changedvram,0,2048); del - if (da2->fullchange) - { + // memset(changedvram,0,2048); del + if (da2->fullchange) { da2->fullchange--; } } - if (da2->vc == da2->vsyncstart) - { + if (da2->vc == da2->vsyncstart) { int wx, wy; - //da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); + // da2_log("VC vsync %i %i\n", da2->firstline_draw, da2->lastline_draw); da2->dispon = 0; da2->cgastat |= 8; x = da2->hdisp; - //if (da2->interlace && !da2->oddeven) da2->lastline++; - //if (da2->interlace && da2->oddeven) da2->firstline--; + // if (da2->interlace && !da2->oddeven) da2->lastline++; + // if (da2->interlace && da2->oddeven) da2->firstline--; wx = x; wy = da2->lastline - da2->firstline; @@ -2868,57 +2842,62 @@ void da2_poll(void* priv) da2_doblit(da2->firstline_draw, da2->lastline_draw + 1, wx, wy, da2); da2->firstline = 2000; - da2->lastline = 0; + da2->lastline = 0; da2->firstline_draw = 2000; - da2->lastline_draw = 0; + da2->lastline_draw = 0; da2->oddeven ^= 1; changeframecount = da2->interlace ? 3 : 2; - da2->vslines = 0; + da2->vslines = 0; - //if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch + (da2->rowoffset << 1) + ((da2->crtc[5] & 0x60) >> 5); - //else da2->ma = da2->maback = da2->ma_latch + ((da2->crtc[5] & 0x60) >> 5); - //da2->ca = ((da2->crtc[0xe] << 8) | da2->crtc[0xf]) + ((da2->crtc[0xb] & 0x60) >> 5) + da2->ca_adj; -/* if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch; - else*/ da2->ma = da2->maback = da2->ma_latch; - da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj; + // if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch + (da2->rowoffset << 1) + ((da2->crtc[5] & 0x60) >> 5); + // else da2->ma = da2->maback = da2->ma_latch + ((da2->crtc[5] & 0x60) >> 5); + // da2->ca = ((da2->crtc[0xe] << 8) | da2->crtc[0xf]) + ((da2->crtc[0xb] & 0x60) >> 5) + da2->ca_adj; + /* if (da2->interlace && da2->oddeven) da2->ma = da2->maback = da2->ma_latch; + else*/ + da2->ma + = da2->maback = da2->ma_latch; + da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj; da2->ma <<= 1; da2->maback <<= 1; da2->ca <<= 1; - //da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); + // da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); } - if (da2->vc == da2->vtotal) - { - //da2_log("VC vtotal\n"); - //printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); - da2->vc = 0; - da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; - da2->dispon = 1; - da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; + if (da2->vc == da2->vtotal) { + // da2_log("VC vtotal\n"); + // printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend); + da2->vc = 0; + da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f; + da2->dispon = 1; + da2->displine = (da2->interlace && da2->oddeven) ? 1 : 0; da2->scrollcache = da2->attrc[LV_PANNING] & 7; } if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31)) da2->con = 1; } - //printf("2 %i\n",da2_vsyncstart); - //da2_log("da2_poll %i %i %i %i %i %i %i\n", ins, da2->dispofftime, da2->dispontime, da2->vidtime, cyc_total, da2->linepos, da2->vc); - //da2_log("r"); + // printf("2 %i\n",da2_vsyncstart); + // da2_log("da2_poll %i %i %i %i %i %i %i\n", ins, da2->dispofftime, da2->dispontime, da2->vidtime, cyc_total, da2->linepos, da2->vc); + // da2_log("r"); } -static void da2_loadfont(char* fname, void* p) { - da2_t* da2 = (da2_t*)p; +static void +da2_loadfont(char *fname, void *p) +{ + da2_t *da2 = (da2_t *) p; uint8_t buf; - //uint32_t code = 0; + // uint32_t code = 0; uint64_t fsize; - if (!fname) return; - if (*fname == '\0') return; - FILE* mfile = rom_fopen(fname, "rb"); + 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); + // da2_log("MSG: Can't open binary ROM font file: %s\n", fname); return; } fseek(mfile, 0, SEEK_END); @@ -2926,9 +2905,9 @@ static void da2_loadfont(char* fname, void* p) { fseek(mfile, 0, SEEK_SET); if (fsize > DA2_FONTROM_SIZE) { fsize = DA2_FONTROM_SIZE; /* truncate read data */ - //da2_log("MSG: The binary ROM font is truncated: %s\n", fname); - //fclose(mfile); - //return 1; + // da2_log("MSG: The binary ROM font is truncated: %s\n", fname); + // fclose(mfile); + // return 1; } uint32_t j = 0; while (ftell(mfile) < fsize) { @@ -2941,50 +2920,58 @@ static void da2_loadfont(char* fname, void* p) { } /* 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 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 } }; -void da2_reset_ioctl(da2_t* da2) +void +da2_reset_ioctl(da2_t *da2) { - da2->ioctl[LS_RESET] = 0x00; /* Bit 0: Reset sequencer */ + da2->ioctl[LS_RESET] = 0x00; /* Bit 0: Reset sequencer */ da2_outw(LS_INDEX, 0x0302, da2); /* Index 02, Bit 1: VGA passthrough, Bit 0: Character Mode */ da2_outw(LS_INDEX, 0x0008, da2); /* Index 08, Bit 0: Enable MMIO */ } static void -da2_reset(void* priv) +da2_reset(void *priv) { - da2_t* da2 = (da2_t*)priv; + da2_t *da2 = (da2_t *) priv; /* Initialize drawing */ da2->bitblt.exec = DA2_BLT_CIDLE; - da2->render = da2_render_blank; + da2->render = da2_render_blank; da2_reset_ioctl(da2); - da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ - da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ - da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ - da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA-II, 1024 KB */ - da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8 ) << 1); /* Configuration 1 : Monitor ID 3 */ - da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ - da2->fctl[0] = 0x2b; /* 3E3h:0 */ - da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ - da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ - da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ - da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ - da2->ma_latch = 0; - da2->interlace = 0; - da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ - da2->attr_palette_enable = 0; /* disable attribute generator */ + da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ + da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ + da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ + da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA-II, 1024 KB */ + da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8) << 1); /* Configuration 1 : Monitor ID 3 */ + da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ + da2->fctl[0] = 0x2b; /* 3E3h:0 */ + da2->fctl[LF_MMIO_MODE] = 0xb0; /* 3E3h:0bh */ + da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */ + da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */ + da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */ + da2->ma_latch = 0; + da2->interlace = 0; + da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */ + da2->attr_palette_enable = 0; /* disable attribute generator */ /* Set default color palette (Windows 3.1 display driver won't reset palette) */ for (int i = 0; i < 256; i++) { @@ -2993,171 +2980,178 @@ da2_reset(void* priv) da2->vgapal[i].b = ps55_palette_color[i & 0x3F][2]; da2->pallook[i] = makecol32((da2->vgapal[i].r & 0x3f) * 4, (da2->vgapal[i].g & 0x3f) * 4, (da2->vgapal[i].b & 0x3f) * 4); } + da2_log("da2_reset done.\n"); } -static void *da2_init() +static void * +da2_init() { - if (svga_get_pri() == NULL) - return NULL; - svga_t *mb_vga = svga_get_pri(); - mb_vga->cable_connected = 0; + if (svga_get_pri() == NULL) + return NULL; + svga_t *mb_vga = svga_get_pri(); + mb_vga->cable_connected = 0; - da2_t* da2 = malloc(sizeof(da2_t)); - da2->mb_vga = mb_vga; + da2_t *da2 = malloc(sizeof(da2_t)); + da2->mb_vga = mb_vga; - da2->dispontime = 1000ull << 32; - da2->dispofftime = 1000ull << 32; - int memsize = 1024 * 1024; - da2->vram = malloc(memsize); - da2->vram_mask = memsize - 1; - da2->cram = malloc(0x1000); - da2->vram_display_mask = DA2_MASK_CRAM; - da2->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12); /* XX000h */ - da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ + da2->dispontime = 1000ull << 32; + da2->dispofftime = 1000ull << 32; + int memsize = 1024 * 1024; + da2->vram = malloc(memsize); + da2->vram_mask = memsize - 1; + da2->cram = malloc(0x1000); + da2->vram_display_mask = DA2_MASK_CRAM; + da2->changedvram = malloc(/*(memsize >> 12) << 1*/ 0x1000000 >> 12); /* XX000h */ + da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ - da2->mmio.charset = device_get_config_int("charset"); - da2->mmio.font= malloc(DA2_FONTROM_SIZE); - switch(da2->mmio.charset) - { - case DA2_DCONFIG_CHARSET_HANT: - da2_loadfont(DA2_FONTROM_PATH_HANT, da2); - break; - case DA2_DCONFIG_CHARSET_JPAN: - da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); - break; - } + da2->mmio.charset = device_get_config_int("charset"); + da2->mmio.font = malloc(DA2_FONTROM_SIZE); + switch (da2->mmio.charset) { + case DA2_DCONFIG_CHARSET_HANT: + da2_loadfont(DA2_FONTROM_PATH_HANT, da2); + break; + case DA2_DCONFIG_CHARSET_JPAN: + da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); + break; + } - mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); - da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); - memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ + mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); + da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (float) (1ull << 32)); + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ #ifdef ENABLE_DA2_DEBUGBLT - da2->bitblt.debug_reg = malloc(DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE); - da2->mmdbg_fp = fopen("da2_mmiowdat.txt", "w"); - da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); - da2->bitblt.debug_reg_ip = 0; + da2->bitblt.debug_reg = malloc(DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE); + da2->mmdbg_fp = fopen("da2_mmiowdat.txt", "w"); + da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); + da2->bitblt.debug_reg_ip = 0; #endif - da2->bitblt.payload_addr = 0; - da2_reset(da2); - - mem_mapping_add(&da2->mmio.mapping, 0xA0000, 0x20000, da2_mmio_read, da2_mmio_readw, NULL, da2_mmio_write, da2_mmio_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); - //da2_log("DA2mmio new mapping: %X, base: %x, size: %x\n", &da2->mmio.mapping, da2->mmio.mapping.base, da2->mmio.mapping.size); + da2->bitblt.payload_addr = 0; + da2_reset(da2); - mem_mapping_disable(&da2->mmio.mapping); + mem_mapping_add(&da2->mmio.mapping, 0xA0000, 0x20000, da2_mmio_read, da2_mmio_readw, NULL, da2_mmio_write, da2_mmio_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); + // da2_log("DA2mmio new mapping: %X, base: %x, size: %x\n", &da2->mmio.mapping, da2->mmio.mapping.base, da2->mmio.mapping.size); - mem_mapping_add(&da2->cmapping, 0xE0000, 0x1000, da2_code_readb, da2_code_readw, NULL, da2_code_writeb, da2_code_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); + mem_mapping_disable(&da2->mmio.mapping); - mem_mapping_disable(&da2->cmapping); + mem_mapping_add(&da2->cmapping, 0xE0000, 0x1000, da2_code_readb, da2_code_readw, NULL, da2_code_writeb, da2_code_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); - timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ - timer_add(&da2->bitblt.timer, da2_bitblt_exec, da2, 0); + mem_mapping_disable(&da2->cmapping); - return da2; + timer_add(&da2->timer, da2_poll, da2, 0); + da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ + timer_add(&da2->bitblt.timer, da2_bitblt_exec, da2, 0); + + return da2; } -static int da2_available() +static int +da2_available() { - return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); + return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); } -void da2_close(void *p) +void +da2_close(void *p) { - da2_t *da2 = (da2_t *)p; + da2_t *da2 = (da2_t *) p; - /* dump mem for debug */ + /* dump mem for debug */ #ifdef ENABLE_DA2_LOG - FILE* f; - f = fopen("da2_cram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->cram, 0x1000, 1, f); - fclose(f); - } - f = fopen("da2_vram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->vram, 1024*1024, 1, f); - fclose(f); - } - f = fopen("da2_gram.dmp", "wb"); - if (f != NULL) { - fwrite(da2->mmio.ram, 256*1024, 1, f); - fclose(f); - } - f = fopen("da2_attrpal.dmp", "wb"); - if (f != NULL) { - fwrite(da2->attrc, 32, 1, f); - fclose(f); - } - f = fopen("da2_dacrgb.dmp", "wb"); - if (f != NULL) { - fwrite(da2->vgapal, 3*256, 1, f); - fclose(f); - } - f = fopen("da2_daregs.txt", "w"); - if (f != NULL) { - for (int i=0;i<0x10;i++) - fprintf(f, "3e1(ioctl) %02X: %4X\n", i, da2->ioctl[i]); - for (int i = 0; i < 0x20; i++) - fprintf(f, "3e3(fctl) %02X: %4X\n", i, da2->fctl[i]); - for (int i = 0; i < 0x20; i++) - fprintf(f, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); - for (int i = 0; i < 0x40; i++) - fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrc[i]); - for (int i = 0; i < 0x10; i++) - fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); - for (int i = 0; i < 0x10; i++) - fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); - fclose(f); - } + FILE *f; + f = fopen("da2_cram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->cram, 0x1000, 1, f); + fclose(f); + } + f = fopen("da2_vram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->vram, 1024 * 1024, 1, f); + fclose(f); + } + f = fopen("da2_gram.dmp", "wb"); + if (f != NULL) { + fwrite(da2->mmio.ram, 256 * 1024, 1, f); + fclose(f); + } + f = fopen("da2_attrpal.dmp", "wb"); + if (f != NULL) { + fwrite(da2->attrc, 32, 1, f); + fclose(f); + } + f = fopen("da2_dacrgb.dmp", "wb"); + if (f != NULL) { + fwrite(da2->vgapal, 3 * 256, 1, f); + fclose(f); + } + f = fopen("da2_daregs.txt", "w"); + if (f != NULL) { + for (int i = 0; i < 0x10; i++) + fprintf(f, "3e1(ioctl) %02X: %4X\n", i, da2->ioctl[i]); + for (int i = 0; i < 0x20; i++) + fprintf(f, "3e3(fctl) %02X: %4X\n", i, da2->fctl[i]); + for (int i = 0; i < 0x20; i++) + fprintf(f, "3e5(crtc) %02X: %4X\n", i, da2->crtc[i]); + for (int i = 0; i < 0x40; i++) + fprintf(f, "3e8(attr) %02X: %4X\n", i, da2->attrc[i]); + for (int i = 0; i < 0x10; i++) + fprintf(f, "3eb(gcr) %02X: %4X\n", i, da2->gdcreg[i]); + for (int i = 0; i < 0x10; i++) + fprintf(f, "3ee(?) %02X: %4X\n", i, da2->reg3ee[i]); + fclose(f); + } #endif #ifdef ENABLE_DA2_DEBUGBLT - f = fopen("da2_bltdump.csv", "w"); - if (f != NULL && da2->bitblt.debug_reg_ip > 0) { - /* print header */ + f = fopen("da2_bltdump.csv", "w"); + if (f != NULL && da2->bitblt.debug_reg_ip > 0) { + /* print header */ + for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { + if (da2->bitblt.debug_reg[(da2->bitblt.debug_reg_ip - 1) * DA2_DEBUG_BLTLOG_SIZE + y] != DA2_DEBUG_BLT_NEVERUSED) + fprintf(f, "\"%02X\"\t", y); + } + fprintf(f, "\n"); + /* print data */ + for (int x = 0; x < da2->bitblt.debug_reg_ip; x++) { for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { - if (da2->bitblt.debug_reg[(da2->bitblt.debug_reg_ip - 1) * DA2_DEBUG_BLTLOG_SIZE + y] != DA2_DEBUG_BLT_NEVERUSED) - fprintf(f, "\"%02X\"\t", y); + if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_NEVERUSED) + ; + else if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_USEDRESET) + fprintf(f, "\"\"\t"); + else + fprintf(f, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]); } fprintf(f, "\n"); - /* print data */ - for (int x = 0; x < da2->bitblt.debug_reg_ip; x++) { - for (int y = 0; y < DA2_DEBUG_BLTLOG_SIZE; y++) { - if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_NEVERUSED) - ; - else if (da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y] == DA2_DEBUG_BLT_USEDRESET) - fprintf(f, "\"\"\t"); - else - fprintf(f, "\"%X\"\t", da2->bitblt.debug_reg[x * DA2_DEBUG_BLTLOG_SIZE + y]); - } - fprintf(f, "\n"); - } - fclose(f); } - if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); - if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); - free(da2->bitblt.debug_reg); + fclose(f); + } + if (da2->mmdbg_fp != NULL) + fclose(da2->mmdbg_fp); + if (da2->mmrdbg_fp != NULL) + fclose(da2->mmrdbg_fp); + free(da2->bitblt.debug_reg); #endif - free(da2->cram); - free(da2->vram); - free(da2->changedvram); - free(da2->mmio.font); - free(da2); + free(da2->cram); + free(da2->vram); + free(da2->changedvram); + free(da2->mmio.font); + free(da2); } -void da2_speed_changed(void *p) +void +da2_speed_changed(void *p) { - da2_t* da2 = (da2_t*)p; - da2->da2const = (uint64_t)((cpuclock / DA2_PIXELCLOCK) * (float)(1ull << 32)); + da2_t *da2 = (da2_t *) p; + da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (float) (1ull << 32)); da2_recalctimings(da2); } -void da2_force_redraw(void *p) +void +da2_force_redraw(void *p) { - da2_t* da2 = (da2_t*)p; + da2_t *da2 = (da2_t *) p; da2->fullchange = changeframecount; } static const device_config_t da2_configuration[] = { - // clang-format off + // clang-format off { .name = "charset", .description = "Charset", @@ -3197,7 +3191,7 @@ static const device_config_t da2_configuration[] = { } }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on + // clang-format on }; const device_t ps55da2_device = { From 58c5d9606e0c24e86e85e7e7adff2a0e25bb3382 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sun, 16 Feb 2025 23:47:10 +0900 Subject: [PATCH 56/82] fixed some drawing issues in Win 3.1. * Changed bitblt execution. This fixes a mouse cursor color issue in Windows 3.1. * Fixed splash graphics broken in A-Train IV. --- src/video/vid_ps55da2.c | 145 +++++++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 61 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 9ed099f19..060e47ce6 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -237,6 +237,7 @@ #ifdef ENABLE_DA2_LOG # define ENABLE_DA2_DEBUGBLT 1 +// # define ENABLE_DA2_DEBUGFULLSCREEN 1 int da2_do_log = ENABLE_DA2_LOG; static void @@ -609,7 +610,7 @@ da2_bitblt_load(da2_t *da2) { uint32_t value32; uint64_t value64; - da2_log("BITBLT loading params\n"); + da2_log("bltload: loading params\n"); // da2_log("BitBlt memory:\n"); // if (da2->bitblt.payload[0] != 0) // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) @@ -665,17 +666,20 @@ da2_bitblt_load(da2_t *da2) case 0x00: break; default: - da2_log("da2_ParseBLT: Unknown PreOP!\n"); + da2_log("bltload: Unknown PreOP!\n"); break; } i++; } da2->bitblt.exec = DA2_BLT_CIDLE; - /* clear payload memory */ - memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - da2->bitblt.payload_addr = 0; + // /* clear payload memory */ + // memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + // da2->bitblt.payload_addr = 0; /* [89] 20: 0001 (1) then execute payload */ if (da2->bitblt.reg[0x20] & 0x1) { + /* clear payload memory */ + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + da2->bitblt.payload_addr = 0; #ifdef ENABLE_DA2_DEBUGBLT for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { // if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); @@ -690,7 +694,7 @@ da2_bitblt_load(da2_t *da2) #endif da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03; /* 01 AND, 03 XOR */ - da2_log("bitblt execute 05: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); + da2_log("bltload_exec: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); for (int i = 0; i <= 0xb; i++) da2_log("%02x ", da2->gdcreg[i]); da2_log("\n"); @@ -820,11 +824,12 @@ void da2_bitblt_exec(void *p) { da2_t *da2 = (da2_t *) p; - timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + // timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + da2_log("bitblt_exec: %d\n", da2->bitblt.exec); // da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); switch (da2->bitblt.exec) { case DA2_BLT_CIDLE: - timer_disable(&da2->bitblt.timer); + // timer_disable(&da2->bitblt.timer); break; case DA2_BLT_CLOAD: da2->bitblt.indata = 0; @@ -960,17 +965,30 @@ da2_bitblt_exec(void *p) } } void -da2_bitblt_dopayload(da2_t *da2) +da2_bitblt_dopayload(void *priv) { - if (da2->bitblt.exec == DA2_BLT_CIDLE) { - da2->bitblt.exec = DA2_BLT_CLOAD; - // timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ - da2_log("da2 Do bitblt\n"); - while (da2->bitblt.exec != DA2_BLT_CIDLE) { + da2_t *da2 = (da2_t *) priv; + timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); + // if (da2->bitblt.indata) /* for OS/2 J1.3 */ + // { + // if (da2->bitblt.exec == DA2_BLT_CIDLE) { + // da2->bitblt.exec = DA2_BLT_CLOAD; + // /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ + // da2_log("da2 Do bitblt\n"); + // while (da2->bitblt.exec != DA2_BLT_CIDLE) { + // da2_bitblt_exec(da2); + // } + // da2_log("da2 End bitblt %x\n", da2->bitblt.exec); + // } + // } + if (da2->bitblt.exec != DA2_BLT_CIDLE) + da2_bitblt_exec(da2); + else if (da2->bitblt.indata) /* for OS/2 J1.3 */ + { + if (da2->bitblt.exec == DA2_BLT_CIDLE) { + da2->bitblt.exec = DA2_BLT_CLOAD; da2_bitblt_exec(da2); } - da2_log("da2 End bitblt %x\n", da2->bitblt.exec); } } @@ -1091,7 +1109,9 @@ da2_out(uint16_t addr, uint16_t val, void *p) case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ case LC_V_DISPLAY_ENABLE_END: /* Vertical Display End Register */ case LC_START_VERTICAL_BLANK: /* Start Vertical Blank Register */ - // val = 0x400; /* for debugging bitblt in Win 3.x */ +#ifdef ENABLE_DA2_DEBUGFULLSCREEN + val = 0x400; /* for debugging bitblt in Win 3.x */ +#endif break; case LC_VIEWPORT_SELECT: /* ViewPort Select? */ // return; @@ -1204,7 +1224,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); return; } - da2->gdcreg[da2->gdcaddr & 15] = val & 0xff; + da2->gdcreg[da2->gdcaddr & 0x0f] = val & 0xff; break; // case 0x3ed: /* used by Windows 3.1 display driver */ // da2->gdcreg[5] = val & 0xff; @@ -1280,11 +1300,11 @@ da2_in(uint16_t addr, void *p) temp |= 0x80; } temp &= 0xf6; /* clear busy bit */ - if (da2->bitblt.indata) /* for OS/2 J1.3 */ - da2_bitblt_dopayload(da2); + // if (da2->bitblt.indata) /* for OS/2 J1.3 */ + // da2_bitblt_dopayload(da2); if (da2->bitblt.exec != DA2_BLT_CIDLE) { // da2_log("exec:%x\n", da2->bitblt.exec); - temp |= 0x08; // wait(bit 3 + bit 0) + temp |= 0x01; // wait(bit 3 + bit 0) // if (!da2->bitblt.timer.enabled) //{ // da2_log("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); @@ -1292,8 +1312,8 @@ da2_in(uint16_t addr, void *p) // } } if (da2->bitblt.indata) - temp |= 0x01; - // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); + temp |= 0x08; + da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); } // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); break; @@ -2143,8 +2163,10 @@ da2_mapping_update(da2_t *da2) mem_mapping_enable(&da2->cmapping); mem_mapping_enable(&da2->mmio.mapping); timer_enable(&da2->timer); + timer_enable(&da2->bitblt.timer); } else { da2_log("DA2 disable registers\n"); + timer_disable(&da2->bitblt.timer); timer_disable(&da2->timer); mem_mapping_disable(&da2->cmapping); mem_mapping_disable(&da2->mmio.mapping); @@ -2193,28 +2215,28 @@ da2_mca_reset(void *p) } static void -da2_gdcropB(uint32_t addr, da2_t *da2) +da2_gdcropB(uint32_t addr,uint8_t bitmask, da2_t *da2) { for (int i = 0; i < 8; i++) { if (da2->writemask & (1 << i)) { - // da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW]); + // da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, bitmask); switch (da2->gdcreg[LG_COMMAND] & 0x03) { case 0: /*Set*/ - // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); - da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->gdcsrc[i] & ~bitmask); + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->vram[addr | i] & ~bitmask); + da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->vram[addr | i] & ~bitmask); break; case 1: /*AND*/ - // da2->vram[addr | i] = (da2->gdcinput[i] | ~da2->gdcreg[LG_BIT_MASK_LOW]) & da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + // da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask) & da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask); break; case 2: /*OR*/ - // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) | da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask); break; case 3: /*XOR*/ - // da2->vram[addr | i] = (da2->gdcinput[i] & da2->gdcreg[LG_BIT_MASK_LOW]) ^ da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->vram[addr | i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) ^ da2->gdcsrc[i]; + da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask); break; } } @@ -2303,15 +2325,13 @@ da2_mmio_read(uint32_t addr, void *p) return DA2_INVALIDACCESS8; /* invalid memory access */ break; } - } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 or 256 color mode */ - { + } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 8 or 256 color mode */ cycles -= video_timing_read_b; for (int i = 0; i < 8; i++) da2->gdcla[i] = da2->vram[(addr << 3) | i]; /* read in byte */ // da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); if (da2->gdcreg[LG_MODE] & 0x08) { /* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint8_t ret = 0; - for (int i = 0; i < 8; i++) { if (~da2->gdcreg[LG_COLOR_DONT_CARE] & (1 << i)) /* color don't care register */ ret |= da2->gdcla[i] ^ ((da2->gdcreg[LG_COLOR_COMPAREJ] & (1 << i)) ? 0xff : 0); @@ -2319,8 +2339,8 @@ da2_mmio_read(uint32_t addr, void *p) return ~ret; } else return da2->gdcla[da2->readplane]; - } else /* text mode 3 */ - { + } else { /* text mode 3 */ + cycles -= video_timing_read_b; return da2->vram[addr]; } @@ -2329,7 +2349,7 @@ static uint16_t da2_mmio_readw(uint32_t addr, void *p) { da2_t *da2 = (da2_t *) p; - da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + //da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); if (da2->ioctl[LS_MMIO] & 0x10) { return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 color or 256 color mode */ @@ -2419,9 +2439,12 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); break; } - } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 color or 256 color mode */ - { + } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 8 color or 256 color mode */ uint8_t wm = da2->writemask; + uint8_t bitmask; + /* align bitmask to even address */ + if (addr & 1) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + else bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; // da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); #ifdef ENABLE_DA2_DEBUGBLT // if (!(da2->gdcreg[LG_COMMAND] & 0x08)) @@ -2460,20 +2483,20 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2->gdcinput[i] = ~val; else da2->gdcinput[i] = val; - da2_gdcropB(addr, da2); + da2_gdcropB(addr, bitmask, da2); return; } switch (da2->writemode) { - case 2: + case 2: /* equiv to vga write mode 1 */ for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) da2->vram[addr | i] = da2->gdcsrc[i]; break; - case 0: + case 0:/* equiv to vga write mode 0 */ if (da2->gdcreg[LG_DATA_ROTATION] & 7) val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - if (da2->gdcreg[LG_BIT_MASK_LOW] == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { + if (bitmask == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) da2->vram[addr | i] = val; @@ -2486,38 +2509,39 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) for (int i = 0; i < 8; i++) da2->debug_vramold[i] = da2->vram[addr | i]; /* use latch */ - da2_gdcropB(addr, da2); + da2_gdcropB(addr, bitmask, da2); // for (int i = 0; i < 8; i++) - // da2_log("\tsrc %02x in %02x bitm %02x mod %x rop %x: %02x -> %02x\n", da2->gdcsrc[i], da2->gdcinput[i], da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch + // da2_log("\tsrc %02x in %02x bitm %02x mod %x rop %x: %02x -> %02x\n", da2->gdcsrc[i], da2->gdcinput[i], bitmask, da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch ////da2_log("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); } break; - case 1: + case 1:/* equiv to vga write mode 2 */ if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) - da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & da2->gdcreg[LG_BIT_MASK_LOW]) | (da2->gdcsrc[i] & ~da2->gdcreg[LG_BIT_MASK_LOW]); + da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + fprintf(da2->mmdbg_fp, "m1-1"); } else { for (int i = 0; i < 8; i++) da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); - da2_gdcropB(addr, da2); + da2_gdcropB(addr, bitmask, da2); + fprintf(da2->mmdbg_fp, "m1-2"); } break; - case 3: + case 3:/* equiv to vga write mode 3 */ if (da2->gdcreg[LG_DATA_ROTATION] & 7) val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - wm = da2->gdcreg[LG_BIT_MASK_LOW]; - da2->gdcreg[LG_BIT_MASK_LOW] &= val; + wm = bitmask; + bitmask &= val; for (int i = 0; i < 8; i++) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; - da2_gdcropB(addr, da2); - da2->gdcreg[LG_BIT_MASK_LOW] = wm; + da2_gdcropB(addr, bitmask, da2); + bitmask = wm; break; } // da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); - } else /* mode 3h text */ - { + } else { /* mode 3h text */ cycles -= video_timing_write_b; da2->vram[addr] = val; da2->fullchange = 2; @@ -2644,8 +2668,7 @@ da2_mmio_writew(uint32_t addr, uint16_t val, void *p) // da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); - } else if (!(da2->ioctl[LS_MODE] & 1)) /* 8 color or 256 color mode */ - { + } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 8 color or 256 color mode */ addr &= DA2_MASK_MMIO; // return; // da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); @@ -3039,7 +3062,7 @@ da2_init() timer_add(&da2->timer, da2_poll, da2, 0); da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ - timer_add(&da2->bitblt.timer, da2_bitblt_exec, da2, 0); + timer_add(&da2->bitblt.timer, da2_bitblt_dopayload, da2, 0); return da2; } From f6b6e39349b5cbe83a8d5d8859dbd4c7be28e4b6 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 17 Feb 2025 00:06:47 +0900 Subject: [PATCH 57/82] cleanup format --- src/disk/hdc_esdi_mca.c | 74 +++++++++++------------------------------ 1 file changed, 20 insertions(+), 54 deletions(-) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index df2a26349..690f658a0 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1385,9 +1385,7 @@ esdi_init(UNUSED(const device_t *info)) if (info->local == ESDI_IS_ADAPTER) { dev->pos_regs[0] = 0xff; dev->pos_regs[1] = 0xdd; - } - else if (info->local == ESDI_IS_INTEGRATED) - { + } else if (info->local == ESDI_IS_INTEGRATED) { dev->pos_regs[0] = 0x9f; dev->pos_regs[1] = 0xdf; } @@ -1400,8 +1398,7 @@ esdi_init(UNUSED(const device_t *info)) mca_add_to_slot(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, esdi_reset, dev, slotno - 1); else mca_add(esdi_mca_read, esdi_integrated_mca_write, esdi_mca_feedb, esdi_reset, dev); - } - else + } else mca_add(esdi_mca_read, esdi_mca_write, esdi_mca_feedb, NULL, dev); /* Mark for a reset. */ @@ -1453,56 +1450,25 @@ const device_t esdi_ps2_device = { }; static device_config_t -esdi_integrated_config[] = -{ - { - .name = "in_esdi_slot", - .description = "Slot #", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "Auto", - .value = 0 - }, - { - .description = "1", - .value = 1 - }, - { - .description = "2", - .value = 2 - }, - { - .description = "3", - .value = 3 - }, - { - .description = "4", - .value = 4 - }, - { - .description = "5", - .value = 5 - }, - { - .description = "6", - .value = 6 - }, - { - .description = "7", - .value = 7 - }, - { - .description = "8", - .value = 8 - } - }, - .default_int = 0 + esdi_integrated_config[] = { + { + .name = "in_esdi_slot", + .description = "Slot #", + .type = CONFIG_SELECTION, + .selection = { + { .description = "Auto", .value = 0 }, + { .description = "1", .value = 1 }, + { .description = "2", .value = 2 }, + { .description = "3", .value = 3 }, + { .description = "4", .value = 4 }, + { .description = "5", .value = 5 }, + { .description = "6", .value = 6 }, + { .description = "7", .value = 7 }, + { .description = "8", .value = 8 } + }, + .default_int = 0 }, - { - .type = -1 - } + { .type = -1 } }; const device_t From 5314f519adb59f4aa70f3ad68d3c47c627087451 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 17 Feb 2025 00:11:33 +0900 Subject: [PATCH 58/82] cleanup format --- src/floppy/fdc.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index a8d2e6520..8a1a33f2f 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -744,13 +744,11 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h. If it fails, then floppy drives will be treated as DD drives. */ if (fdc->flags & FDC_FLAG_PS2_MCA) { - if (val & 0x04) - { - fdc->tfifo = 8; + if (val & 0x04) { + fdc->tfifo = 8; fdc->fifointest = 1; - } - else { - fdc->tfifo = 1; + } else { + fdc->tfifo = 1; fdc->fifointest = 0; } } @@ -767,10 +765,9 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->dsr = val; return; case 5: /*Command register*/ - if (fdc->fifointest) - { + 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); + fdc_log("FIFO buffer position = %X\n", ((fifo_t *) fdc->fifo_p)->end); fifo_write(val, fdc->fifo_p); if (fifo_get_full(fdc->fifo_p)) fdc->stat &= ~0x80; @@ -1368,8 +1365,7 @@ fdc_read(uint16_t addr, void *priv) ret = fdc->stat; break; case 5: /*Data*/ - if (fdc->fifointest) - { + if (fdc->fifointest) { /* Read FIFO buffer in the test mode (PS/55) */ ret = fifo_read(fdc->fifo_p); break; From 5c4fcfaf8525768dccaad201ad7e7911f475c1b9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Feb 2025 04:49:43 +0100 Subject: [PATCH 59/82] ESC/P Printer: No longer assume roms/ is where the binary is, fixes #5221. --- src/include/86box/plat.h | 4 +- src/include/86box/rom.h | 1 + src/io.c | 104 ++++++++++++++++++++++++++++++++++--- src/mem/rom.c | 42 +++++++++++++++ src/printer/prt_escp.c | 10 ++-- src/qt/languages/86box.pot | 6 +++ src/qt/languages/ca-ES.po | 6 +++ src/qt/languages/cs-CZ.po | 6 +++ src/qt/languages/de-DE.po | 6 +++ src/qt/languages/es-ES.po | 6 +++ src/qt/languages/fi-FI.po | 6 +++ src/qt/languages/fr-FR.po | 6 +++ src/qt/languages/hr-HR.po | 10 +++- src/qt/languages/hu-HU.po | 6 +++ src/qt/languages/it-IT.po | 8 ++- src/qt/languages/ja-JP.po | 6 +++ src/qt/languages/ko-KR.po | 6 +++ src/qt/languages/nl-NL.po | 6 +++ src/qt/languages/pl-PL.po | 6 +++ src/qt/languages/pt-BR.po | 6 +++ src/qt/languages/pt-PT.po | 6 +++ src/qt/languages/ru-RU.po | 6 +++ src/qt/languages/sk-SK.po | 6 +++ src/qt/languages/sl-SI.po | 10 +++- src/qt/languages/tr-TR.po | 6 +++ src/qt/languages/uk-UA.po | 6 +++ src/qt/languages/vi-VN.po | 6 +++ src/qt/languages/zh-CN.po | 6 +++ src/qt/languages/zh-TW.po | 8 ++- src/qt/qt_platform.cpp | 2 + 30 files changed, 300 insertions(+), 19 deletions(-) diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index f39f6ba51..81874685e 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -50,7 +50,9 @@ enum { STRING_HW_NOT_AVAILABLE_DEVICE, /* "Device \"%hs\" is not available..." */ STRING_MONITOR_SLEEP, /* "Monitor in sleep mode" */ STRING_GHOSTPCL_ERROR_TITLE, /* "Unable to initialize GhostPCL" */ - STRING_GHOSTPCL_ERROR_DESC /* "gpcl6dll32.dll/gpcl6dll64.dll/libgpcl6 is required..." */ + STRING_GHOSTPCL_ERROR_DESC, /* "gpcl6dll32.dll/gpcl6dll64.dll/libgpcl6 is required..." */ + STRING_ESCP_ERROR_TITLE, /* "Unable to find Dot-Matrix fonts" */ + STRING_ESCP_ERROR_DESC /* "TrueType fonts in the \"roms/printer/fonts\" directory..." */ }; /* The Win32 API uses _wcsicmp. */ diff --git a/src/include/86box/rom.h b/src/include/86box/rom.h index 1f6e611b1..83fd7cf90 100644 --- a/src/include/86box/rom.h +++ b/src/include/86box/rom.h @@ -52,6 +52,7 @@ extern uint8_t rom_read(uint32_t addr, void *priv); extern uint16_t rom_readw(uint32_t addr, void *priv); extern uint32_t rom_readl(uint32_t addr, void *priv); +extern void rom_get_full_path(char *dest, const char *fn); extern FILE *rom_fopen(const char *fn, char *mode); extern int rom_getfile(char *fn, char *s, int size); extern int rom_present(const char *fn); diff --git a/src/io.c b/src/io.c index 27f8503b0..2565ac537 100644 --- a/src/io.c +++ b/src/io.c @@ -30,6 +30,7 @@ #include "cpu.h" #include <86box/m_amstrad.h> #include <86box/pci.h> +#include <86box/mem.h> #define NPORTS 65536 /* PC/AT supports 64K ports */ @@ -59,6 +60,7 @@ int initialized = 0; io_t *io[NPORTS]; io_t *io_last[NPORTS]; +// #define ENABLE_IO_LOG 1 #ifdef ENABLE_IO_LOG int io_do_log = ENABLE_IO_LOG; @@ -69,7 +71,8 @@ io_log(const char *fmt, ...) if (io_do_log) { va_start(ap, fmt); - pclog_ex(fmt, ap); + if (CS == 0xf000) + pclog_ex(fmt, ap); va_end(ap); } } @@ -77,6 +80,18 @@ io_log(const char *fmt, ...) # define io_log(fmt, ...) #endif +uint16_t last_port_read = 0xffff; + +static void +print_lpr(void) +{ + FILE *f = fopen("d:\\86boxnew\\ndiags.dmp", "wb"); + fwrite(&(ram[0x24c30]), 1, 65536, f); + fclose(f); + + pclog("last_port_read = %04X\n", last_port_read); +} + void io_init(void) { @@ -106,6 +121,8 @@ io_init(void) /* io[c] should be NULL. */ io[c] = io_last[c] = NULL; } + + atexit(print_lpr); } void @@ -333,6 +350,11 @@ io_debug_check_addr(uint16_t addr) } #endif +#include <86box/random.h> + +uint8_t post_code = 0xc6; +uint8_t action = 0x00; + uint8_t inb(uint16_t port) { @@ -393,7 +415,33 @@ inb(uint16_t port) ret = 0xfe; #endif - io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); +#if 0 + if (port == 0x5f7) + ret = 0xaf; +#endif + + if (port == 0x379) + ret &= 0xf8; + + // io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); + + // if (CS == 0xc000) + // pclog("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, port, ret); + + // if (port == 0x62) + // ret = 0xf2; + + // if (port == 0x62) + // ret |= random_generate() & 0x80; + + // if ((port >= 0x60) && (port <= 0x66)) + // pclog("[%04X:%04X] [R] %04X = %02X\n", CS, cpu_state.pc, port, ret); + + if ((port != 0x0061) && (port != 0x0177) && (port != 0x01f7) && (port != 0x0376) && (port != 0x03c7) && (port != 0x03c8) && (port != 0x03c9) && (port != 0x03f6) && (port != 0x03da)) { + io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); + } + + last_port_read = port; return ret; } @@ -447,7 +495,20 @@ outb(uint16_t port, uint8_t val) #endif } - io_log("[%04X:%08X] (%i, %i, %04i) outb(%04X, %02X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + // io_log("[%04X:%08X] (%i, %i, %04i) outb(%04X, %02X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + + if (port == 0x0068) + action = val; + + if (port == 0x0080) + post_code = val; + + // if (port == 0x3db) + // pclog("[%04X:%04X] [W] %04X = %02X\n", CS, cpu_state.pc, port, val); + + if ((port != 0x0061) && (port != 0x00ed) && (port != 0x03c7) && (port != 0x03c8) && (port != 0x03c9)) { + io_log("[%04X:%08X] (%i, %i, %04i) outb(%04X, %02X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + } return; } @@ -525,7 +586,9 @@ inw(uint16_t port) if (!found) cycles -= io_delay; - io_log("[%04X:%08X] (%i, %i, %04i) in w(%04X) = %04X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); + if (1) { + io_log("[%04X:%08X] (%i, %i, %04i) in w(%04X) = %04X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); + } return ret; } @@ -594,7 +657,21 @@ outw(uint16_t port, uint16_t val) #endif } - io_log("[%04X:%08X] (%i, %i, %04i) outw(%04X, %04X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + if (port == 0x0080) + post_code = val; + +#if 0 + if (port == 0x0c02) { + if (val) + mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + else + mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + } +#endif + + if (1) { + io_log("[%04X:%08X] (%i, %i, %04i) outw(%04X, %04X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + } return; } @@ -704,7 +781,9 @@ inl(uint16_t port) if (!found) cycles -= io_delay; - io_log("[%04X:%08X] (%i, %i, %04i) in l(%04X) = %08X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); + if (1) { + io_log("[%04X:%08X] (%i, %i, %04i) in l(%04X) = %08X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); + } return ret; } @@ -791,7 +870,9 @@ outl(uint16_t port, uint32_t val) #endif } - io_log("[%04X:%08X] (%i, %i, %04i) outl(%04X, %08X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + if (1) { + io_log("[%04X:%08X] (%i, %i, %04i) outl(%04X, %08X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); + } return; } @@ -801,6 +882,7 @@ io_trap_readb(uint16_t addr, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(1, addr, 0, 0, trap->priv); + pclog("[%04X:%08X] io_trap_readb(%04X)\n", CS, cpu_state.pc, addr); return 0xff; } @@ -809,6 +891,7 @@ io_trap_readw(uint16_t addr, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(2, addr, 0, 0, trap->priv); + pclog("[%04X:%08X] io_trap_readw(%04X)\n", CS, cpu_state.pc, addr); return 0xffff; } @@ -817,6 +900,7 @@ io_trap_readl(uint16_t addr, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(4, addr, 0, 0, trap->priv); + pclog("[%04X:%08X] io_trap_readl(%04X)\n", CS, cpu_state.pc, addr); return 0xffffffff; } @@ -825,6 +909,7 @@ io_trap_writeb(uint16_t addr, uint8_t val, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(1, addr, 1, val, trap->priv); + pclog("[%04X:%08X] io_trap_writeb(%04X)\n", CS, cpu_state.pc, addr); } static void @@ -832,6 +917,7 @@ io_trap_writew(uint16_t addr, uint16_t val, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(2, addr, 1, val, trap->priv); + pclog("[%04X:%08X] io_trap_writew(%04X)\n", CS, cpu_state.pc, addr); } static void @@ -839,6 +925,7 @@ io_trap_writel(uint16_t addr, uint32_t val, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(4, addr, 1, val, trap->priv); + pclog("[%04X:%08X] io_trap_writel(%04X)\n", CS, cpu_state.pc, addr); } void * @@ -885,6 +972,9 @@ io_trap_remap(void *handle, int enable, uint16_t addr, uint16_t size) io_trap_writeb, io_trap_writew, io_trap_writel, trap); } + + if ((addr == 0x0170) || (addr == 0x0376) || (addr == 0x01f0) || (addr == 0x03f6)) + pclog("io_trap_remape(%04X) = %i\n", addr, trap->enable); } void diff --git a/src/mem/rom.c b/src/mem/rom.c index f9718b7ce..8b2308402 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -86,6 +86,48 @@ rom_add_path(const char *path) path_slash(rom_path->path); } +static int +rom_check(const char *fn) +{ + FILE *fp = NULL; + int ret = 0; + + if ((fn[strlen(fn) - 1] == '/') || (fn[strlen(fn) - 1] == '\\')) + ret = plat_dir_check((char *) fn); + else { + fp = fopen(fn, "rb"); + ret = (fp != NULL); + fclose(fp); + } + + return ret; +} + +void +rom_get_full_path(char *dest, const char *fn) +{ + char temp[1024] = { 0 }; + + dest[0] = 0x00; + + if (strstr(fn, "roms/") == fn) { + /* Relative path */ + for (rom_path_t *rom_path = &rom_paths; rom_path != NULL; rom_path = rom_path->next) { + path_append_filename(temp, rom_path->path, fn + 5); + + if (rom_check(temp)) { + strcpy(dest, temp); + return; + } + } + + return; + } else { + /* Absolute path */ + strcpy(dest, fn); + } +} + FILE * rom_fopen(const char *fn, char *mode) { diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index 0198444a0..d0836e5f2 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -1968,16 +1968,16 @@ escp_init(void *lpt) dev->ctrl = 0x04; dev->lpt = lpt; + rom_get_full_path(dev->fontpath, "roms/printer/fonts/"); + /* Create a full pathname for the font files. */ - if (strlen(exe_path) >= sizeof(dev->fontpath)) { + if (strlen(dev->fontpath) == 0) { + ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_ESCP_ERROR_TITLE), + plat_get_string(STRING_ESCP_ERROR_DESC)); free(dev); return (NULL); } - strcpy(dev->fontpath, exe_path); - path_slash(dev->fontpath); - strcat(dev->fontpath, "roms/printer/fonts/"); - /* Create the full path for the page images. */ path_append_filename(dev->pagepath, usr_path, "printer"); if (!plat_dir_check(dev->pagepath)) diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index ac2db7d07..65cc32f85 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -2135,3 +2135,9 @@ msgstr "" msgid "Generic PC/AT Memory Expansion" msgstr "" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index e49ab3223..cf3d5c7f7 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -2129,3 +2129,9 @@ msgstr "Expansió de memòria genèrica PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Expansió de memòria genèrica PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "No es pot trobar tipus de lletra de matriu de punts" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Els tipus de lletra TrueType al directori \"roms/printer/fonts\" són necessaris per a l'emulació de la impressora de matriu de punts ESC/P genèrica." diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index cafadd63b..e3d85dd09 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -2129,3 +2129,9 @@ msgstr "Obecné rozšíření paměti PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Obecné rozšíření paměti PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Nastala chyba při nachození jehličkových písem" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Pro emulaci obecné jehličkové tiskárny ESC/P jsou vyžadována písma TrueType ve složce \"roms/printer/fonts\"." diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index aa666cc48..c904cad0d 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -2132,3 +2132,9 @@ msgstr "Generische PC/XT-Speichererweiterung" msgid "Generic PC/AT Memory Expansion" msgstr "Generische PC/AT-Speichererweiterung" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Nadel-Schriften konnten nicht gefunden werden" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "TrueType-Schriften in das \"roms/printer/fonts\"-Verzeichnis sind für die Allgemeines ESC/P Nadel-Druckers erforderlich." diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 5cac8968f..ca7a3ad53 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -2128,3 +2128,9 @@ msgstr "Expansión de Memoria Generica PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Expansión de Memoria Generica PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "No fué posible encontrar las fuentes matriciales" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Las fuentes TrueType en el directorio \"roms/printer/fonts\" son necesarias para la emulación de la impresora matricial ESC/P genérica." diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index 21dcfd1bc..f044365f0 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -2129,3 +2129,9 @@ msgstr "Yleinen PC/XT-muistilaajennus" msgid "Generic PC/AT Memory Expansion" msgstr "Yleinen PC/AT-muistilaajennus" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Pistematriisifontteja ei löydy" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "TrueType-fontteja kansiossa \"roms/printer/fonts\"-hakemistoon yleinen ESC/P pistematriisitulostin emulointiin." diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index ff8a5168f..3b283b3dd 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -2129,3 +2129,9 @@ msgstr "Expansion de la mémoire générique PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Expansion de la mémoire générique PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Impossible de trouver les polices à matrice à points" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Les polices TrueType dans le répertoire \"roms/printer/fonts\" sont nécessaires à l'émulation de l'imprimante générique ESC/P à matrice à points." diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index 9d242f8e0..ed4fdf621 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -655,7 +655,7 @@ msgid "ZIP images" msgstr "ZIP slike" msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." -msgstr "86Box nije mogao pronaći upotrebljive ROM datoteke.\n\nMolimte posjetite sknite paket s ROM datotekama i ekstrahirajte paket u \"roms\" mapu." +msgstr "86Box nije mogao pronaći upotrebljive ROM datoteke.\n\nMolimte posjetite sknite paket s ROM datotekama i ekstrahirajte paket u mapu \"roms\"." msgid "(empty)" msgstr "(prazno)" @@ -2062,7 +2062,7 @@ msgid "Generic Text Printer" msgstr "Generični tekstovni pisač" msgid "Generic ESC/P Dot-Matrix Printer" -msgstr "Generični pisač matrični ESC/P" +msgstr "Generični matrični pisač ESC/P" msgid "Generic PostScript Printer" msgstr "Generični pisač PostScript" @@ -2129,3 +2129,9 @@ msgstr "Generičko proširenje memorije PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Generičko proširenje memorije PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Nije moguće pronaći matrične fontove" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "TrueType fontovi u mapi \"roms/printer/fonts\" potrebni su za emulaciju generičnog matričnog pisača ESC/P." diff --git a/src/qt/languages/hu-HU.po b/src/qt/languages/hu-HU.po index 2b5adacf4..b4afd8010 100644 --- a/src/qt/languages/hu-HU.po +++ b/src/qt/languages/hu-HU.po @@ -2129,3 +2129,9 @@ msgstr "Általános PC/XT memóriabővítők" msgid "Generic PC/AT Memory Expansion" msgstr "Általános PC/AT memóriabővítők" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Nem találja a Dot-Matrix betűtípusokat" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Az általános ESC/P pontmátrixnyomtató emulációjához a \"roms/printer/fonts\" könyvtárban található TrueType betűtípusok szükségesek." diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index c9af80127..73ec57ec0 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -655,7 +655,7 @@ msgid "ZIP images" msgstr "Immagini ZIP" msgid "86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory." -msgstr "86Box non può trovare immagini ROM utilizzabili.\n\nPlease download a ROM set and extract it into the \"roms\" directory." +msgstr "86Box non può trovare immagini ROM utilizzabili.\n\nSi prega di scaricare un set di ROM ed estrarlo nella directory \"roms\"." msgid "(empty)" msgstr "(empty)" @@ -2129,3 +2129,9 @@ msgstr "Espansione di memoria generica PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Espansione di memoria generica PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Impossibile trovare i font a matrice di punti" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "I font TrueType presenti nella directory \"roms/printer/fonts\" sono necessari per l'emulazione della stampante a matrice di punti ESC/P generica." diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 9a3289b51..9c6fa66e7 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -2129,3 +2129,9 @@ msgstr "汎用PC/XTメモリ拡張カード" msgid "Generic PC/AT Memory Expansion" msgstr "汎用PC/ATメモリ拡張カード" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "ドットマトリクスフォントが見つかりません" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "汎用ESC/Pドットマトリクスプリンタのエミュレーションには、roms/printer/fontsディレクトリ内のTrueTypeフォントが必要です。" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index c6928ad43..ec4b20d0d 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -2129,3 +2129,9 @@ msgstr "일반 PC/XT 메모리 확장 카드" msgid "Generic PC/AT Memory Expansion" msgstr "일반 PC/AT 메모리 확장 카드" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "도트 매트릭스 글꼴을 찾을 수 없습니다" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "일반 ESC/P 도트 매트릭스 프린터의 에뮬레이션을 사용하려면 \"roms/printer/fonts\" 디렉터리에 있는 트루타입 글꼴이 필요합니다." diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 27870db90..c601197ac 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -2129,3 +2129,9 @@ msgstr "Generieke PC/XT geheugenuitbreiding" msgid "Generic PC/AT Memory Expansion" msgstr "Generieke PC/AT geheugenuitbreiding" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Dot-matrix-lettertypen niet gevonden" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "TrueType lettertypen in de map \"roms/printer/fonts\" zijn nodig voor de emulatie van de generieke ESC/P dot-matrix-printer." diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index e42904458..78ded239f 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -2129,3 +2129,9 @@ msgstr "Generyczne rozszerzenie pamięci PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Generyczne rozszerzenie pamięci PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Nie można znaleźć czcionek igłowych" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Czcionki TrueType w katalogu \"roms/printer/fonts\" są wymagane do emulacji generyczniej drukarki igłowej ESC/P." diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index de1bcd544..1594e30ab 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -2129,3 +2129,9 @@ msgstr "Expansão de memória genérica PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Expansão de memória genérica PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Não foi possível localizar os fontes matriciais de pontos" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "As fontes TrueType no diretório \"roms/printer/fonts\" são necessárias para a emulação da impressora matricial de pontos ESC/P genérica." diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index d4c8bf170..b31f020d4 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -2129,3 +2129,9 @@ msgstr "Expansão de memória genérica PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Expansão de memória genérica PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Não foi possível encontrar os fontes matriciais de pontos" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "As fontes TrueType no diretório \"roms/printer/fonts\" são necessárias para a emulação da impressora matricial de pontos ESC/P genérica" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index a2e352faa..a8a4b7794 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -2135,3 +2135,9 @@ msgstr "Стандартное расширение памяти PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Стандартное расширение памяти PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Невозможно найти матричные шрифты" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Шрифты TrueType в каталоге \"roms/printer/fonts\" необходимы для эмуляции стандартного матричного принтера ESC/P." diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index 6b2074d47..e789d9ef9 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -2129,3 +2129,9 @@ msgstr "Všeobecné rozšírenie pamäte PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Všeobecné rozšírenie pamäte PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Nastala chyba pri hľadaní ihličkových písem" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Písma TrueType v adresári \"roms/printer/fonts\" sú potrebné na emuláciu generickej ihličkovej tlačiarne ESC/P." diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 9d8ccaaf9..1394a3635 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -823,10 +823,10 @@ msgid "Are you sure you want to exit 86Box?" msgstr "Ste prepričani, da želite zapreti 86Box?" msgid "Unable to initialize Ghostscript" -msgstr "Ne morem inicializirati Ghostscript" +msgstr "Ghostscript-a ni bilo mogoče inicializirati" msgid "Unable to initialize GhostPCL" -msgstr "Ne morem inicializirati GhostPCL" +msgstr "GhostPCL-ja ni bilo mogoče inicializirati" msgid "MO %i (%ls): %ls" msgstr "MO %i (%ls): %ls" @@ -2129,3 +2129,9 @@ msgstr "Generična razširitev pomnilnika PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Generična razširitev pomnilnika PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Matričnih pisav ni bilo mogoče najti" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Matrične pisave v imeniku \"roms/printer/fonts\" so potrebne za emulacijo generičnega matričnega tiskalnika ESC/P." diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index 288412154..81866b3ce 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -2129,3 +2129,9 @@ msgstr "Sıradan PC/XT bellek artırma" msgid "Generic PC/AT Memory Expansion" msgstr "Sıradan PC/AT bellek artırma" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Dot Matrix yazı tipleri bulunamıyor" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Sıradan ESC/P Dot Matrix Yazıcının emülasyonu için \"roms/printer/fonts\" dizinindeki TrueType yazı tipleri gereklidir." diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 5ce59be01..9b57ac03e 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -2135,3 +2135,9 @@ msgstr "Загальне розширення пам'яті PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Загальне розширення пам'яті PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Неможливо знайти матричні шрифти" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Шрифти TrueType у каталозі \"roms/printer/fonts\" потрібні для емуляції загального матричного принтера Generic ESC/P." diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 707c7ae7f..fafbbc160 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -2129,3 +2129,9 @@ msgstr "Chung mở rộng bộ nhớ qua PC/XT" msgid "Generic PC/AT Memory Expansion" msgstr "Chung mở rộng bộ nhớ qua PC/AT" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "Không tìm thấy phông chữ ma trận chấm" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "Cần có phông chữ TrueType trong thư mục \"roms/printer/fonts\" để mô phỏng máy in generic ESC/P ma trận chấm." diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index 81451b2b3..ec5d2c252 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -2129,3 +2129,9 @@ msgstr "通用 PC/XT 内存扩展" msgid "Generic PC/AT Memory Expansion" msgstr "通用 PC/AT 内存扩展" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "无法找到点阵字体" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "仿真通用 ESC/P 点阵打印机需要使用 \"roms/printer/fonts\" 目录中的 TrueType 字体。" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 9bf8edfc6..b0d8163cb 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -2062,7 +2062,7 @@ msgid "Generic Text Printer" msgstr "通用文字印表機" msgid "Generic ESC/P Dot-Matrix Printer" -msgstr "通用 ESC/P 點矩陣" +msgstr "通用 ESC/P 點矩陣印表機" msgid "Generic PostScript Printer" msgstr "通用 PostScript 印表機" @@ -2129,3 +2129,9 @@ msgstr "通用 PC/XT 記憶體擴充" msgid "Generic PC/AT Memory Expansion" msgstr "通用 PC/AT 記憶體擴充" + +msgid "Unable to find Dot-Matrix fonts" +msgstr "無法找到點矩陣字型" + +msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulation of the Generic ESC/P Dot-Matrix Printer." +msgstr "通用 ESC/P 點矩陣印表機的模擬需要 \"roms/printer/fonts\" 目錄中的 TrueType 字體。" diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index dd6c34efc..561c94d8a 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -639,6 +639,8 @@ ProgSettings::reloadStrings() translatedstrings[STRING_MONITOR_SLEEP] = QCoreApplication::translate("", "Monitor in sleep mode").toStdWString(); translatedstrings[STRING_NET_ERROR] = QCoreApplication::translate("", "Failed to initialize network driver").toStdWString(); translatedstrings[STRING_NET_ERROR_DESC] = QCoreApplication::translate("", "The network configuration will be switched to the null driver").toStdWString(); + translatedstrings[STRING_ESCP_ERROR_TITLE] = QCoreApplication::translate("", "Unable to find Dot-Matrix fonts").toStdWString(); + translatedstrings[STRING_ESCP_ERROR_DESC] = QCoreApplication::translate("", "TrueType fonts in the \"roms/printer/fonts\" directory are required for the emulatio of the Generic ESC/P Dot-Matrix Printer.").toStdWString(); } wchar_t * From a6a377757f3098eeb38ec3a71c725d31a897de53 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Feb 2025 04:57:49 +0100 Subject: [PATCH 60/82] Paradise VGA: Override the horizontal skew handling, fixes #5228. --- src/video/vid_paradise.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index d0acaf276..da8bb9aa6 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -571,6 +571,8 @@ paradise_init(const device_t *info, uint32_t memory) paradise->type = info->local; + svga->hoverride = 1; + return paradise; } From f68810b2777ccfa749efe89bc815648fa8651a73 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Feb 2025 15:20:16 +0100 Subject: [PATCH 61/82] Reverted the io.c changes that should not have been committed. --- src/io.c | 104 ++++--------------------------------------------------- 1 file changed, 7 insertions(+), 97 deletions(-) diff --git a/src/io.c b/src/io.c index 2565ac537..27f8503b0 100644 --- a/src/io.c +++ b/src/io.c @@ -30,7 +30,6 @@ #include "cpu.h" #include <86box/m_amstrad.h> #include <86box/pci.h> -#include <86box/mem.h> #define NPORTS 65536 /* PC/AT supports 64K ports */ @@ -60,7 +59,6 @@ int initialized = 0; io_t *io[NPORTS]; io_t *io_last[NPORTS]; -// #define ENABLE_IO_LOG 1 #ifdef ENABLE_IO_LOG int io_do_log = ENABLE_IO_LOG; @@ -71,8 +69,7 @@ io_log(const char *fmt, ...) if (io_do_log) { va_start(ap, fmt); - if (CS == 0xf000) - pclog_ex(fmt, ap); + pclog_ex(fmt, ap); va_end(ap); } } @@ -80,18 +77,6 @@ io_log(const char *fmt, ...) # define io_log(fmt, ...) #endif -uint16_t last_port_read = 0xffff; - -static void -print_lpr(void) -{ - FILE *f = fopen("d:\\86boxnew\\ndiags.dmp", "wb"); - fwrite(&(ram[0x24c30]), 1, 65536, f); - fclose(f); - - pclog("last_port_read = %04X\n", last_port_read); -} - void io_init(void) { @@ -121,8 +106,6 @@ io_init(void) /* io[c] should be NULL. */ io[c] = io_last[c] = NULL; } - - atexit(print_lpr); } void @@ -350,11 +333,6 @@ io_debug_check_addr(uint16_t addr) } #endif -#include <86box/random.h> - -uint8_t post_code = 0xc6; -uint8_t action = 0x00; - uint8_t inb(uint16_t port) { @@ -415,33 +393,7 @@ inb(uint16_t port) ret = 0xfe; #endif -#if 0 - if (port == 0x5f7) - ret = 0xaf; -#endif - - if (port == 0x379) - ret &= 0xf8; - - // io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); - - // if (CS == 0xc000) - // pclog("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, port, ret); - - // if (port == 0x62) - // ret = 0xf2; - - // if (port == 0x62) - // ret |= random_generate() & 0x80; - - // if ((port >= 0x60) && (port <= 0x66)) - // pclog("[%04X:%04X] [R] %04X = %02X\n", CS, cpu_state.pc, port, ret); - - if ((port != 0x0061) && (port != 0x0177) && (port != 0x01f7) && (port != 0x0376) && (port != 0x03c7) && (port != 0x03c8) && (port != 0x03c9) && (port != 0x03f6) && (port != 0x03da)) { - io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); - } - - last_port_read = port; + io_log("[%04X:%08X] (%i, %i, %04i) in b(%04X) = %02X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); return ret; } @@ -495,20 +447,7 @@ outb(uint16_t port, uint8_t val) #endif } - // io_log("[%04X:%08X] (%i, %i, %04i) outb(%04X, %02X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); - - if (port == 0x0068) - action = val; - - if (port == 0x0080) - post_code = val; - - // if (port == 0x3db) - // pclog("[%04X:%04X] [W] %04X = %02X\n", CS, cpu_state.pc, port, val); - - if ((port != 0x0061) && (port != 0x00ed) && (port != 0x03c7) && (port != 0x03c8) && (port != 0x03c9)) { - io_log("[%04X:%08X] (%i, %i, %04i) outb(%04X, %02X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); - } + io_log("[%04X:%08X] (%i, %i, %04i) outb(%04X, %02X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); return; } @@ -586,9 +525,7 @@ inw(uint16_t port) if (!found) cycles -= io_delay; - if (1) { - io_log("[%04X:%08X] (%i, %i, %04i) in w(%04X) = %04X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); - } + io_log("[%04X:%08X] (%i, %i, %04i) in w(%04X) = %04X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); return ret; } @@ -657,21 +594,7 @@ outw(uint16_t port, uint16_t val) #endif } - if (port == 0x0080) - post_code = val; - -#if 0 - if (port == 0x0c02) { - if (val) - mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); - else - mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - } -#endif - - if (1) { - io_log("[%04X:%08X] (%i, %i, %04i) outw(%04X, %04X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); - } + io_log("[%04X:%08X] (%i, %i, %04i) outw(%04X, %04X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); return; } @@ -781,9 +704,7 @@ inl(uint16_t port) if (!found) cycles -= io_delay; - if (1) { - io_log("[%04X:%08X] (%i, %i, %04i) in l(%04X) = %08X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); - } + io_log("[%04X:%08X] (%i, %i, %04i) in l(%04X) = %08X\n", CS, cpu_state.pc, in_smm, found, qfound, port, ret); return ret; } @@ -870,9 +791,7 @@ outl(uint16_t port, uint32_t val) #endif } - if (1) { - io_log("[%04X:%08X] (%i, %i, %04i) outl(%04X, %08X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); - } + io_log("[%04X:%08X] (%i, %i, %04i) outl(%04X, %08X)\n", CS, cpu_state.pc, in_smm, found, qfound, port, val); return; } @@ -882,7 +801,6 @@ io_trap_readb(uint16_t addr, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(1, addr, 0, 0, trap->priv); - pclog("[%04X:%08X] io_trap_readb(%04X)\n", CS, cpu_state.pc, addr); return 0xff; } @@ -891,7 +809,6 @@ io_trap_readw(uint16_t addr, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(2, addr, 0, 0, trap->priv); - pclog("[%04X:%08X] io_trap_readw(%04X)\n", CS, cpu_state.pc, addr); return 0xffff; } @@ -900,7 +817,6 @@ io_trap_readl(uint16_t addr, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(4, addr, 0, 0, trap->priv); - pclog("[%04X:%08X] io_trap_readl(%04X)\n", CS, cpu_state.pc, addr); return 0xffffffff; } @@ -909,7 +825,6 @@ io_trap_writeb(uint16_t addr, uint8_t val, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(1, addr, 1, val, trap->priv); - pclog("[%04X:%08X] io_trap_writeb(%04X)\n", CS, cpu_state.pc, addr); } static void @@ -917,7 +832,6 @@ io_trap_writew(uint16_t addr, uint16_t val, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(2, addr, 1, val, trap->priv); - pclog("[%04X:%08X] io_trap_writew(%04X)\n", CS, cpu_state.pc, addr); } static void @@ -925,7 +839,6 @@ io_trap_writel(uint16_t addr, uint32_t val, void *priv) { io_trap_t *trap = (io_trap_t *) priv; trap->func(4, addr, 1, val, trap->priv); - pclog("[%04X:%08X] io_trap_writel(%04X)\n", CS, cpu_state.pc, addr); } void * @@ -972,9 +885,6 @@ io_trap_remap(void *handle, int enable, uint16_t addr, uint16_t size) io_trap_writeb, io_trap_writew, io_trap_writel, trap); } - - if ((addr == 0x0170) || (addr == 0x0376) || (addr == 0x01f0) || (addr == 0x03f6)) - pclog("io_trap_remape(%04X) = %i\n", addr, trap->enable); } void From 464253a8cd4dcbfd3c857ace6dfabe3be2a315ef Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Feb 2025 19:48:31 +0100 Subject: [PATCH 62/82] IDE: Fix device bus flags. --- src/disk/hdc_ide.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index b69ddf128..fb95bef28 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -3338,7 +3338,7 @@ const device_t ide_vlb_device = { const device_t ide_vlb_sec_device = { .name = "VLB IDE Controller (Secondary)", .internal_name = "ide_vlb_sec", - .flags = DEVICE_VLB | DEVICE_ISA16, + .flags = DEVICE_VLB, .local = 2, .init = ide_sec_init, .close = ide_sec_close, @@ -3352,7 +3352,7 @@ const device_t ide_vlb_sec_device = { const device_t ide_vlb_2ch_device = { .name = "VLB IDE Controller (Dual-Channel)", .internal_name = "ide_vlb_2ch", - .flags = DEVICE_VLB | DEVICE_ISA16, + .flags = DEVICE_VLB, .local = 3, .init = ide_init, .close = ide_close, @@ -3366,7 +3366,7 @@ const device_t ide_vlb_2ch_device = { const device_t ide_pci_device = { .name = "PCI IDE Controller", .internal_name = "ide_pci", - .flags = DEVICE_PCI | DEVICE_ISA16, + .flags = DEVICE_PCI, .local = 4, .init = ide_init, .close = ide_close, @@ -3380,7 +3380,7 @@ const device_t ide_pci_device = { const device_t ide_pci_sec_device = { .name = "PCI IDE Controller (Secondary)", .internal_name = "ide_pci_sec", - .flags = DEVICE_PCI | DEVICE_ISA16, + .flags = DEVICE_PCI, .local = 4, .init = ide_sec_init, .close = ide_sec_close, @@ -3394,7 +3394,7 @@ const device_t ide_pci_sec_device = { const device_t ide_pci_2ch_device = { .name = "PCI IDE Controller (Dual-Channel)", .internal_name = "ide_pci_2ch", - .flags = DEVICE_PCI | DEVICE_ISA16, + .flags = DEVICE_PCI, .local = 5, .init = ide_init, .close = ide_close, From 45dc381251e5769fccc0fe4f0575ae77a8bf3a40 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 17 Feb 2025 19:50:53 +0100 Subject: [PATCH 63/82] Forgot the single-channel VLB controller. --- src/disk/hdc_ide.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index fb95bef28..125cd806d 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -3324,7 +3324,7 @@ const device_t ide_isa_2ch_device = { const device_t ide_vlb_device = { .name = "VLB IDE Controller", .internal_name = "ide_vlb", - .flags = DEVICE_VLB | DEVICE_ISA16, + .flags = DEVICE_VLB, .local = 2, .init = ide_init, .close = ide_close, From a6e866c0e547f4bffca287e425bdf598e7966a62 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 18 Feb 2025 22:34:27 +0900 Subject: [PATCH 64/82] added comments --- src/disk/hdc_esdi_mca.c | 16 ++++++++++++++-- src/floppy/fdc.c | 2 +- src/machine/m_ps2_mca.c | 6 +++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 690f658a0..8f1def137 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1471,16 +1471,28 @@ static device_config_t { .type = -1 } }; +/* +Device for an IBM DBA (Direct Bus Attachment) hard disk. +The Disk BIOS is included in the System ROM. +Some models have an exclusive channel slot for the DBA hard disk. +Following IBM machines are supported: + * PS/2 model 55SX + * PS/2 model 65SX + * PS/2 model 70 type 3 (Slot #4) + * PS/2 model 70 type 4 (Slot #4) + * PS/55 model 5550-T (Slot #5) + * PS/55 model 5550-V (Slot #5) +*/ const device_t esdi_integrated_device = { - .name = "IBM Integrated Fixed Disk Controller (MCA)", + .name = "IBM Integrated Fixed Disk and Controller (MCA)", .internal_name = "esdi_integrated_mca", .flags = DEVICE_MCA, .local = ESDI_IS_INTEGRATED, .init = esdi_init, .close = esdi_close, .reset = esdi_reset, - .available = NULL, /* The Disk BIOS is included in the System ROM */ + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = esdi_integrated_config diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 8a1a33f2f..5de1a8ef4 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -740,7 +740,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) drive = real_drive(fdc, fdc->dor & 3); fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); } - /* Bit 2: FIFO test mode (PS/55 only? This is not documented in neither the PS/2 HITR nor the 82077AA datasheet.) + /* Bit 2: FIFO test mode (PS/55 5550-S,T only. Undocumented) The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h. If it fails, then floppy drives will be treated as DD drives. */ if (fdc->flags & FDC_FLAG_PS2_MCA) { diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 1edff2991..ac22af2fe 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1890,7 +1890,11 @@ machine_ps55_model_50t_init(const machine_t* model) * Planar ID * FFFAh - PS/55 model 5551-S0x, T0x (stage 1?) * FFEEh - PS/55 model 5551-S1x, T1x (stage 2?) - * POST (P/N 38F6933) determination: FBxx -> 4 slots (error), xxEE -> 5 slots (ok), others -> 8 (error) + * Verification in BIOS P/N 38F6933: FBxx -> 4 slots (error), xxEE -> 5 slots (ok), others -> 8 (error) + * + * The only difference between S and T models is the CPU speed (16 MHz vs 20 MHz). + * The POST measures the speed, and sets a flag in the BIOS Data Area to indicate the sub model. + * The VM in 86Box runs faster than the real, so the POST always determines it as the T model. */ ps2.planar_id = 0xffee; ps55_mca_board_model_50t_init(); From 2c78e7bb2f5710bfbe57877422b8b6e96c8e3999 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 18 Feb 2025 22:46:18 +0900 Subject: [PATCH 65/82] added comments --- src/disk/hdc_esdi_mca.c | 16 ++++++++++++++-- src/floppy/fdc.c | 2 +- src/machine/m_ps2_mca.c | 6 +++++- src/video/vid_svga.c | 6 +++--- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 690f658a0..8f1def137 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -1471,16 +1471,28 @@ static device_config_t { .type = -1 } }; +/* +Device for an IBM DBA (Direct Bus Attachment) hard disk. +The Disk BIOS is included in the System ROM. +Some models have an exclusive channel slot for the DBA hard disk. +Following IBM machines are supported: + * PS/2 model 55SX + * PS/2 model 65SX + * PS/2 model 70 type 3 (Slot #4) + * PS/2 model 70 type 4 (Slot #4) + * PS/55 model 5550-T (Slot #5) + * PS/55 model 5550-V (Slot #5) +*/ const device_t esdi_integrated_device = { - .name = "IBM Integrated Fixed Disk Controller (MCA)", + .name = "IBM Integrated Fixed Disk and Controller (MCA)", .internal_name = "esdi_integrated_mca", .flags = DEVICE_MCA, .local = ESDI_IS_INTEGRATED, .init = esdi_init, .close = esdi_close, .reset = esdi_reset, - .available = NULL, /* The Disk BIOS is included in the System ROM */ + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = esdi_integrated_config diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 8a1a33f2f..5de1a8ef4 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -740,7 +740,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) drive = real_drive(fdc, fdc->dor & 3); fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); } - /* Bit 2: FIFO test mode (PS/55 only? This is not documented in neither the PS/2 HITR nor the 82077AA datasheet.) + /* Bit 2: FIFO test mode (PS/55 5550-S,T only. Undocumented) The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h. If it fails, then floppy drives will be treated as DD drives. */ if (fdc->flags & FDC_FLAG_PS2_MCA) { diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 1edff2991..ac22af2fe 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1890,7 +1890,11 @@ machine_ps55_model_50t_init(const machine_t* model) * Planar ID * FFFAh - PS/55 model 5551-S0x, T0x (stage 1?) * FFEEh - PS/55 model 5551-S1x, T1x (stage 2?) - * POST (P/N 38F6933) determination: FBxx -> 4 slots (error), xxEE -> 5 slots (ok), others -> 8 (error) + * Verification in BIOS P/N 38F6933: FBxx -> 4 slots (error), xxEE -> 5 slots (ok), others -> 8 (error) + * + * The only difference between S and T models is the CPU speed (16 MHz vs 20 MHz). + * The POST measures the speed, and sets a flag in the BIOS Data Area to indicate the sub model. + * The VM in 86Box runs faster than the real, so the POST always determines it as the T model. */ ps2.planar_id = 0xffee; ps55_mca_board_model_50t_init(); diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index db378b754..caa20e196 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -512,9 +512,9 @@ svga_in(uint16_t addr, void *priv) /* The IBM PS/55 Display Adapter has own Monitor Type Detection bit in the different I/O port (I/O 3E0h, 3E1h). When the monitor cable is connected to the Display Adapter, the port 3C2h returns the value as 'no cable connection'. - The POST of PS/55 has an extra code that tries detecting the monitor on the planar VGA. - If it fails, then the POST reads the NVRAM set by the reference diskette, and writes the BIOS Data Area (Mem 487h, 489h). - MONCHK.EXE in the reference diskette uses both I/O ports to determine the monitor type, and writes the BDA. + The POST of PS/55 has an extra code. If the monitor is not detected on the planar VGA, + it reads the POS data in NVRAM set by the reference diskette, and writes the BIOS Data Area (Mem 487h, 489h). + MONCHK.EXE in the reference diskette uses both I/O ports to determine the monitor type, updates the NVRAM and BDA. */ if (svga->vgapal[0].r >= 10 || svga->vgapal[0].g >= 10 || svga->vgapal[0].b >= 10) ret = 0; From 244f7665580767eec6b7f6b24a8e01eb1987795d Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 18 Feb 2025 23:45:16 +0900 Subject: [PATCH 66/82] fix unexpected write to null fp in rel build --- src/video/vid_ps55da2.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 060e47ce6..ba6835e8c 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -369,8 +369,10 @@ typedef struct da2_t { int raster_op; uint8_t payload[DA2_BLT_MEMSIZE]; int32_t reg[DA2_BLT_REGSIZE]; // must be signed int +#ifdef ENABLE_DA2_DEBUGBLT int32_t *debug_reg; // for debug int debug_reg_ip; // for debug +#endif int payload_addr; pc_timer_t timer; int64_t timerspeed; @@ -387,10 +389,12 @@ typedef struct da2_t { int x, y; } bitblt; +#ifdef ENABLE_DA2_DEBUGBLT FILE *mmdbg_fp; FILE *mmrdbg_fp; uint32_t mmdbg_vidaddr; uint32_t mmrdbg_vidaddr; +#endif uint8_t pos_regs[8]; svga_t *mb_vga; @@ -2520,12 +2524,12 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); - fprintf(da2->mmdbg_fp, "m1-1"); + //fprintf(da2->mmdbg_fp, "m1-1"); } else { for (int i = 0; i < 8; i++) da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); da2_gdcropB(addr, bitmask, da2); - fprintf(da2->mmdbg_fp, "m1-2"); + //fprintf(da2->mmdbg_fp, "m1-2"); } break; case 3:/* equiv to vga write mode 3 */ From 61acd4473609faddb2ee5ef84f2082412a4da8ea Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 19 Feb 2025 00:16:18 +0900 Subject: [PATCH 67/82] added comment --- src/video/vid_ps55da2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index ba6835e8c..ca4ba85b4 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -96,9 +96,9 @@ [Japanese DOS and Display Adapter compatibility] | POS ID | Adapter Name | K3.31 | J4.04 | J4.08 | OS2 J1.3 | Win3 | |------------|-----------------------------|:-----:|:-----:|:-----:|:--------:|:----:| - | EFFFh | Display Adapter | X | | | ? | | - | FFEDh | ? [Atlas EVT] | X | | | ? | | - | FFFDh | ? [LDT EVT] | X | | | ? | | + | EFFFh | Display Adapter | X | | | | | + | FFEDh | ? [Atlas EVT] | X | | | | | + | FFFDh | ? [LDT EVT] | X | | | | | | EFFEh | Display Adapter II,III,V,B2 | X | X | X | X | X | | E013h | ? [LDT] | X | X | X | X | | | ECCEh | Display Adapter IV | | X | X | X | | @@ -1308,7 +1308,7 @@ da2_in(uint16_t addr, void *p) // da2_bitblt_dopayload(da2); if (da2->bitblt.exec != DA2_BLT_CIDLE) { // da2_log("exec:%x\n", da2->bitblt.exec); - temp |= 0x01; // wait(bit 3 + bit 0) + temp |= 0x01; /* wait (bit 3 + bit 0) ? need verify */ // if (!da2->bitblt.timer.enabled) //{ // da2_log("bitblt timer restarted!! %04X:%04X\n", cs >> 4, cpu_state.pc); From 3c00fece65aff62b03f18b8f953c5006db7dfedb Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 19 Feb 2025 00:37:40 +0900 Subject: [PATCH 68/82] change machine name, update comments --- src/machine/m_ps2_mca.c | 2 +- src/machine/machine_table.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index ac22af2fe..400971138 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1919,7 +1919,7 @@ machine_ps55_model_50v_init(const machine_t* model) /* * Planar ID * F1FFh - PS/55 model 5551-V0x, V1x - * POST (P/N 38F6933) determination: FBxx -> 5 slots (ok), F1xx -> 5 slots (ok), others -> 8 (error) + * Verification in BIOS P/N 56F7416,56F7417: FBxx -> 5 slots (ok), F1xx -> 5 slots (ok), others -> 8 (error) */ ps2.planar_id = 0xf1ff; ps55_mca_board_model_50v_init(); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index bf540922b..7ec31892a 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -5680,7 +5680,7 @@ const machine_t machines[] = { }, /* Has IBM PS/55 5551-V0x, V1x firmware. */ { - .name = "[MCA] IBM PS/55 model 5550-V0", + .name = "[MCA] IBM PS/55 model 5550-V", .internal_name = "ibmps55_m50v", .type = MACHINE_TYPE_386DX, .chipset = MACHINE_CHIPSET_PROPRIETARY, From 2d115e9b8481069e2f56a258dedce32f2f6192a0 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 19 Feb 2025 11:02:28 +0900 Subject: [PATCH 69/82] added patch for font rom, cleanup * Added magic code for OS/2 J1.3 to disable BitBlt's text drawing function that is not implemented yet. * Added comments * Cleanup --- src/video/vid_ps55da2.c | 46 ++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index ca4ba85b4..ad27c978c 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -7,6 +7,17 @@ * This file is part of the 86Box distribution. * * IBM PS/55 Display Adapter II (and its successors) emulation. + * + * Notes: There are some known issues that should be corrected. + * - Incorrect foreground text color appears on an active window in OS/2 J1.3. + * - BitBlt's text drawing function does not work correctly. + * - The screen resolution and blanking interval time maybe not correct. + * + * The code should be tested with following cases. + * - Execute MODE 0, 1, 3 and 4 commands in DOS K3.3 to test various video modes. + * - Run SAMPLE program with the BASIC interpreter in DOS K3.3. + * - Run DOS J4.0 install program to test video mode 03. + * - Run Win 3.1 (IBM-J OEM) and OS/2 J1.3 with 16 and 256 color driver to test BilBlt operations. * * Authors: Akamaki. * @@ -662,9 +673,9 @@ da2_bitblt_load(da2_t *da2) value64 |= da2->bitblt.payload[i + 3]; value64 <<= 8; value64 |= da2->bitblt.payload[i + 2]; - da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; i += 7; break; case 0x00: @@ -699,9 +710,12 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03; /* 01 AND, 03 XOR */ da2_log("bltload_exec: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); - for (int i = 0; i <= 0xb; i++) - da2_log("%02x ", da2->gdcreg[i]); - da2_log("\n"); + // for (int i = 0; i <= 0xb; i++) + // { + // da2_log("%02x ", da2->gdcreg[i]); + // da2->gdcreg[i] = da2->bitblt.reg[i] & 0xff; + // } + // da2_log("\n"); da2->bitblt.destaddr = da2->bitblt.reg[0x29]; da2->bitblt.size_x = da2->bitblt.reg[0x33]; @@ -919,7 +933,7 @@ da2_bitblt_exec(void *p) da2->bitblt.destaddr -= 2; da2->bitblt.srcaddr -= 2; break; - case DA2_BLT_CPUTCHAR: + case DA2_BLT_CPUTCHAR: /* used in OS/2 J1.3 wo ROM patch. TODO: still not work */ // da2->bitblt.y += 2; da2->bitblt.destaddr = da2->bitblt.reg[0x29] + da2->bitblt.x * 2 + da2->bitblt.y * 130 + 0 + 260; // pclog("scr %x dest %x :", da2->bitblt.srcaddr, da2->bitblt.destaddr); @@ -1346,7 +1360,7 @@ da2_in(uint16_t addr, void *p) if (da2->cgastat & 0x01) da2->cgastat &= ~0x30; else - da2->cgastat ^= 0x30; + da2->cgastat ^= 0x30; /* toggle */ temp = da2->cgastat; } else temp = da2->attrc[da2->attraddr]; @@ -1444,9 +1458,10 @@ da2_outw(uint16_t addr, uint16_t val, void *p) da2_out(addr, val, da2); da2->outflipflop = 0; break; - case 0x3EE: + case AC_REG: + /* no register is revealed */ da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); - da2->reg3ee[val & 0xff] = val >> 8; + da2->reg3ee[val & 0x0f] = val >> 8; break; } } @@ -2444,17 +2459,16 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) break; } } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 8 color or 256 color mode */ - uint8_t wm = da2->writemask; uint8_t bitmask; /* align bitmask to even address */ if (addr & 1) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; else bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; - // da2_log("da2_gcB m%d a%x d%x\n", da2->writemode, addr, val); #ifdef ENABLE_DA2_DEBUGBLT + da2_log("da2_wB %x %02x\n", addr, val); // if (!(da2->gdcreg[LG_COMMAND] & 0x08)) //{ if (((int) addr - (int) da2->mmdbg_vidaddr) > 2 || (((int) da2->mmdbg_vidaddr - (int) addr) > 2) || da2->mmdbg_vidaddr == addr) { - fprintf(da2->mmdbg_fp, "\nB %x ", addr); + fprintf(da2->mmdbg_fp, "\nB %x %02x ", addr, val); for (int i = 0; i <= 0xb; i++) fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); } @@ -2535,13 +2549,11 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) case 3:/* equiv to vga write mode 3 */ if (da2->gdcreg[LG_DATA_ROTATION] & 7) val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; - wm = bitmask; bitmask &= val; for (int i = 0; i < 8; i++) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; da2_gdcropB(addr, bitmask, da2); - bitmask = wm; break; } // da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); @@ -2560,7 +2572,6 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) { da2_t *da2 = (da2_t *) p; - uint8_t wm = da2->writemask; uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; bitmask <<= 8; bitmask |= (uint16_t) da2->gdcreg[LG_BIT_MASK_LOW]; @@ -2651,13 +2662,11 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) case 3: if (da2->gdcreg[LG_DATA_ROTATION] & 15) val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work - wm = bitmask; bitmask &= val; for (int i = 0; i < 8; i++) da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; da2_gdcropW(addr, bitmask, da2); - bitmask = wm; break; } // da2_log("%02x%02x%02x%02x,%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3] @@ -3039,6 +3048,9 @@ da2_init() break; case DA2_DCONFIG_CHARSET_JPAN: da2_loadfont(DA2_FONTROM_PATH_JPAN, da2); + /* Add magic code for OS/2 J1.3. This disables BitBlt's text drawing function. */ + da2->mmio.font[0x1AFFE] = 0x80; + da2->mmio.font[0x1AFFF] = 0x01; break; } @@ -3065,7 +3077,7 @@ da2_init() mem_mapping_disable(&da2->cmapping); timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 1 * TIMER_USEC; /* Todo: Async bitblt won't work in OS/2 J1.3 Command Prompt */ + da2->bitblt.timerspeed = 1 * TIMER_USEC; timer_add(&da2->bitblt.timer, da2_bitblt_dopayload, da2, 0); return da2; From ed555c86d72eb6f3f9bdf7060de5567b779fb63f Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 19 Feb 2025 11:38:00 +0900 Subject: [PATCH 70/82] correct function declaration in m_ps2_mca.c --- src/machine/m_ps2_mca.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 400971138..1a2f4d6c6 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1770,8 +1770,8 @@ machine_ps2_model_70_type4_init(const machine_t *model) return ret; } -void -ps55_mca_board_model_50t_init() +static void +ps55_mca_board_model_50t_init(void) { ps2_mca_board_common_init(); @@ -1814,8 +1814,8 @@ ps55_mca_board_model_50t_init() ps2.mb_vga = (vga_t *)device_add(&ps1vga_mca_device); } -void -ps55_mca_board_model_50v_init() +static void +ps55_mca_board_model_50v_init(void) { ps2_mca_board_common_init(); From 6328d5110825d6a9ff437400bcc2c3adfd59fe0c Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Feb 2025 10:54:22 +0100 Subject: [PATCH 71/82] Gave the PCjr the missing MACHINE_CARTRIDGE flag. --- src/machine/machine_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index b9cc8461b..cc3d6aa9f 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -324,7 +324,7 @@ const machine_t machines[] = { .max_multi = 0 }, .bus_flags = MACHINE_PCJR, - .flags = MACHINE_VIDEO_FIXED, + .flags = MACHINE_VIDEO_FIXED | MACHINE_CARTRIDGE, .ram = { .min = 64, .max = 640, From 655a0075795cfe0154c5fac5e8cef04e9e234c18 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Feb 2025 11:12:49 +0100 Subject: [PATCH 72/82] SLiRP: Introduce a new queue for packets received immediately transmssion - those are now collected into said queue and processed immediately after, improves SLiRP operation. --- src/include/86box/network.h | 12 +++++--- src/network/net_slirp.c | 60 +++++++++++++++++++++++++++---------- src/network/network.c | 37 +++++++++++++++++++++++ 3 files changed, 90 insertions(+), 19 deletions(-) diff --git a/src/include/86box/network.h b/src/include/86box/network.h index 2140d62dd..ef9f291ad 100644 --- a/src/include/86box/network.h +++ b/src/include/86box/network.h @@ -57,7 +57,7 @@ /* Queue size must be a power of 2 */ #define NET_QUEUE_LEN 16 #define NET_QUEUE_LEN_MASK (NET_QUEUE_LEN - 1) -#define NET_QUEUE_COUNT 3 +#define NET_QUEUE_COUNT 4 #define NET_CARD_MAX 4 #define NET_HOST_INTF_MAX 64 @@ -84,9 +84,10 @@ enum { }; enum { - NET_QUEUE_RX = 0, - NET_QUEUE_TX_VM = 1, - NET_QUEUE_TX_HOST = 2 + NET_QUEUE_RX = 0, + NET_QUEUE_TX_VM = 1, + NET_QUEUE_TX_HOST = 2, + NET_QUEUE_RX_ON_TX = 3 }; typedef struct netcard_conf_t { @@ -199,7 +200,10 @@ extern const device_t *network_card_getdevice(int); extern int network_tx_pop(netcard_t *card, netpkt_t *out_pkt); extern int network_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size); extern int network_rx_put(netcard_t *card, uint8_t *bufp, int len); +extern int network_rx_on_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size); +extern int network_rx_on_tx_put(netcard_t *card, uint8_t *bufp, int len); extern int network_rx_put_pkt(netcard_t *card, netpkt_t *pkt); +extern int network_rx_on_tx_put_pkt(netcard_t *card, netpkt_t *pkt); #ifdef EMU_DEVICE_H /* 3Com Etherlink */ diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index 11f1a74b2..203428b83 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -60,16 +60,19 @@ enum { }; typedef struct net_slirp_t { - Slirp *slirp; - uint8_t mac_addr[6]; - netcard_t *card; /* netcard attached to us */ - thread_t *poll_tid; - net_evt_t tx_event; - net_evt_t stop_event; - netpkt_t pkt; - netpkt_t pkt_tx_v[SLIRP_PKT_BATCH]; + Slirp * slirp; + uint8_t mac_addr[6]; + netcard_t * card; /* netcard attached to us */ + thread_t * poll_tid; + net_evt_t rx_event; + net_evt_t tx_event; + net_evt_t stop_event; + netpkt_t pkt; + netpkt_t pkt_tx_v[SLIRP_PKT_BATCH]; + int during_tx; + int recv_on_tx; #ifdef _WIN32 - HANDLE sock_event; + HANDLE sock_event; #else uint32_t pfd_len; uint32_t pfd_size; @@ -184,7 +187,11 @@ net_slirp_send_packet(const void *qp, size_t pkt_len, void *opaque) memcpy(slirp->pkt.data, (uint8_t *) qp, pkt_len); slirp->pkt.len = pkt_len; - network_rx_put_pkt(slirp->card, &slirp->pkt); + if (slirp->during_tx) { + network_rx_on_tx_put_pkt(slirp->card, &slirp->pkt); + slirp->recv_on_tx = 1; + } else + network_rx_put_pkt(slirp->card, &slirp->pkt); return pkt_len; } @@ -324,6 +331,21 @@ net_slirp_in_available(void *priv) net_event_set(&slirp->tx_event); } +static void +net_slirp_rx_deferred_packets(net_slirp_t *slirp) +{ + int packets = 0; + + if (slirp->recv_on_tx) { + do { + packets = network_rx_on_tx_popv(slirp->card, slirp->pkt_tx_v, SLIRP_PKT_BATCH); + for (int i = 0; i < packets; i++) + network_rx_put_pkt(slirp->card, &(slirp->pkt_tx_v[i])); + } while (packets > 0); + slirp->recv_on_tx = 0; + } +} + #ifdef _WIN32 static void net_slirp_thread(void *priv) @@ -352,10 +374,13 @@ net_slirp_thread(void *priv) case NET_EVENT_TX: { + slirp->during_tx = 1; int packets = network_tx_popv(slirp->card, slirp->pkt_tx_v, SLIRP_PKT_BATCH); - for (int i = 0; i < packets; i++) { + for (int i = 0; i < packets; i++) net_slirp_in(slirp, slirp->pkt_tx_v[i].data, slirp->pkt_tx_v[i].len); - } + slirp->during_tx = 0; + + net_slirp_rx_deferred_packets(slirp); } break; @@ -398,10 +423,13 @@ net_slirp_thread(void *priv) if (slirp->pfd[NET_EVENT_TX].revents & POLLIN) { net_event_clear(&slirp->tx_event); + slirp->during_tx = 1; int packets = network_tx_popv(slirp->card, slirp->pkt_tx_v, SLIRP_PKT_BATCH); - for (int i = 0; i < packets; i++) { + for (int i = 0; i < packets; i++) net_slirp_in(slirp, slirp->pkt_tx_v[i].data, slirp->pkt_tx_v[i].len); - } + slirp->during_tx = 0; + + net_slirp_rx_deferred_packets(slirp); } } @@ -477,6 +505,7 @@ net_slirp_init(const netcard_t *card, const uint8_t *mac_addr, UNUSED(void *priv slirp->pkt_tx_v[i].data = calloc(1, NET_MAX_FRAME); } slirp->pkt.data = calloc(1, NET_MAX_FRAME); + net_event_init(&slirp->rx_event); net_event_init(&slirp->tx_event); net_event_init(&slirp->stop_event); #ifdef _WIN32 @@ -531,8 +560,9 @@ net_slirp_close(void *priv) slirp_log("SLiRP: waiting for thread to end...\n"); thread_wait(slirp->poll_tid); - net_event_close(&slirp->tx_event); net_event_close(&slirp->stop_event); + net_event_close(&slirp->tx_event); + net_event_close(&slirp->rx_event); slirp_cleanup(slirp->slirp); for (int i = 0; i < SLIRP_PKT_BATCH; i++) { free(slirp->pkt_tx_v[i].data); diff --git a/src/network/network.c b/src/network/network.c index 66990e51d..047642085 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -643,6 +643,43 @@ network_rx_put(netcard_t *card, uint8_t *bufp, int len) return ret; } +int +network_rx_on_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size) +{ + int pkt_count = 0; + + netqueue_t *queue = &card->queues[NET_QUEUE_RX_ON_TX]; + for (int i = 0; i < vec_size; i++) { + if (!network_queue_get_swap(queue, pkt_vec)) + break; + network_dump_packet(pkt_vec); + pkt_count++; + pkt_vec++; + } + + return pkt_count; +} + +int +network_rx_on_tx_put(netcard_t *card, uint8_t *bufp, int len) +{ + int ret = 0; + + ret = network_queue_put(&card->queues[NET_QUEUE_RX_ON_TX], bufp, len); + + return ret; +} + +int +network_rx_on_tx_put_pkt(netcard_t *card, netpkt_t *pkt) +{ + int ret = 0; + + ret = network_queue_put_swap(&card->queues[NET_QUEUE_RX_ON_TX], pkt); + + return ret; +} + int network_rx_put_pkt(netcard_t *card, netpkt_t *pkt) { From c7d9b4c5e78eae31390b4c05045675f2462bdd6e Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Feb 2025 11:21:50 +0100 Subject: [PATCH 73/82] PS/55: Fix some warnings and compile-breaking errors. --- src/device/keyboard.c | 3 +++ src/include/86box/machine.h | 2 +- src/video/vid_ps55da2.c | 8 ++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/device/keyboard.c b/src/device/keyboard.c index de97592bf..2b851f36c 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -85,6 +85,8 @@ typedef struct { const uint8_t brk[4]; } scconvtbl; +/* Is this a left-over of something planned earlier? */ +#ifdef USE_SCCONV55_82 static scconvtbl scconv55_82[18 + 1] = { // clang-format off @@ -109,6 +111,7 @@ static scconvtbl scconv55_82[18 + 1] = {.sc = 0 , .mk = { 0 }, .brk = { 0 } } /* end */ // clang-format on }; +#endif static scconvtbl scconv55_8a[18 + 1] = { diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 690d867db..78f4902eb 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -903,7 +903,7 @@ extern int machine_ps2_model_70_type3_init(const machine_t *); extern int machine_ps2_model_80_init(const machine_t *); extern int machine_ps2_model_80_axx_init(const machine_t *); extern int machine_ps2_model_70_type4_init(const machine_t *); -extern int machine_ps55_model_50t_init(const machine_t*);; +extern int machine_ps55_model_50t_init(const machine_t*); extern int machine_ps55_model_50v_init(const machine_t*); /* m_tandy.c */ diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index ad27c978c..aaf5d4803 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1256,8 +1256,8 @@ da2_out(uint16_t addr, uint16_t val, void *p) uint16_t da2_in(uint16_t addr, void *p) { - da2_t *da2 = (da2_t *) p; - uint16_t temp; + da2_t *da2 = (da2_t *) p; + uint16_t temp = 0xff; switch (addr) { case 0x3c3: @@ -3020,7 +3020,7 @@ da2_reset(void *priv) } static void * -da2_init() +da2_init(UNUSED(const device_t *info)) { if (svga_get_pri() == NULL) return NULL; @@ -3083,7 +3083,7 @@ da2_init() return da2; } static int -da2_available() +da2_available(void) { return (rom_present(DA2_FONTROM_PATH_HANT) || rom_present(DA2_FONTROM_PATH_JPAN)); } From 83d840381a08339a4f275b38a918841633558325 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Feb 2025 11:58:13 +0100 Subject: [PATCH 74/82] Fixed more warnings and compile-breaking mistakes. --- src/machine/m_ps2_mca.c | 8 ++++---- src/sound/resid-fp/SID.cpp | 2 ++ src/sound/resid-fp/WaveformGenerator.cpp | 4 ++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 1a2f4d6c6..d3f881b24 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -375,7 +375,7 @@ ps55_model_50t_read(uint16_t port) return ps2.planar_id >> 8; case 0x102: return ps2.option[0]; - case 0x103: + case 0x103: { uint8_t val = 0xff; /* I/O 103h - Bit 7-4: Memory Card ID (Connector 1 or 3) @@ -413,7 +413,7 @@ ps55_model_50t_read(uint16_t port) } ps2_mca_log(" Read MCA %04X %02X %04X:%04X mem_size = %d, ps2option1 = %2X\n", port, val, cs >> 4, cpu_state.pc, mem_size, ps2.option[1]); return val; - case 0x104: + } case 0x104: return ps2.option[2]; case 0x105: return ps2.option[3]; @@ -435,7 +435,7 @@ ps55_model_50v_read(uint16_t port) return ps2.planar_id >> 8; case 0x102: return ps2.option[0]; - case 0x103: + case 0x103: { uint8_t val = 0xff; /* I/O 103h - Bit 7-4: Reserved @@ -460,7 +460,7 @@ ps55_model_50v_read(uint16_t port) break; } return val; - case 0x104: + } case 0x104: /* Reading cache ID (bit 3-2) always returns zero */ return ps2.option[2] & 0xf3; case 0x105: diff --git a/src/sound/resid-fp/SID.cpp b/src/sound/resid-fp/SID.cpp index 5b5506bc3..4db69af0c 100644 --- a/src/sound/resid-fp/SID.cpp +++ b/src/sound/resid-fp/SID.cpp @@ -107,8 +107,10 @@ constexpr unsigned int OSC_DAC_BITS = 12; * On my 6581R4AR has 0x3A as the only value giving the same output level as 1.prg */ //@{ +#ifdef USE_RESID_UNUSED constexpr unsigned int OFFSET_6581 = 0x380; constexpr unsigned int OFFSET_8580 = 0x9c0; +#endif //@} /** diff --git a/src/sound/resid-fp/WaveformGenerator.cpp b/src/sound/resid-fp/WaveformGenerator.cpp index be0738bba..847560f2a 100644 --- a/src/sound/resid-fp/WaveformGenerator.cpp +++ b/src/sound/resid-fp/WaveformGenerator.cpp @@ -43,7 +43,9 @@ namespace reSIDfp constexpr unsigned int FLOATING_OUTPUT_TTL_6581R3 = 54000; constexpr unsigned int FLOATING_OUTPUT_FADE_6581R3 = 1400; // ~1s +#ifdef USE_RESID_UNUSED constexpr unsigned int FLOATING_OUTPUT_TTL_6581R4 = 1000000; +#endif // ~1s constexpr unsigned int FLOATING_OUTPUT_TTL_8580R5 = 800000; constexpr unsigned int FLOATING_OUTPUT_FADE_8580R5 = 50000; @@ -61,7 +63,9 @@ constexpr unsigned int FLOATING_OUTPUT_FADE_8580R5 = 50000; constexpr unsigned int SHIFT_REGISTER_RESET_6581R3 = 50000; constexpr unsigned int SHIFT_REGISTER_FADE_6581R3 = 15000; // ~2.15s +#ifdef USE_RESID_UNUSED constexpr unsigned int SHIFT_REGISTER_RESET_6581R4 = 2150000; +#endif // ~2.8s constexpr unsigned int SHIFT_REGISTER_RESET_8580R5 = 986000; constexpr unsigned int SHIFT_REGISTER_FADE_8580R5 = 314300; From c262760155c617cf9130ed616303af760f838d37 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Feb 2025 12:56:22 +0100 Subject: [PATCH 75/82] PS/1: Move NVR initialization to the end of ps1_setup(), fixes segmentation fault due to the BIOS language being obtained from the wrong device. --- src/machine/m_ps1.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 130481394..41821a4a8 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -320,30 +320,28 @@ ps1_setup(int model) mem_remap_top(384); - device_add(&ps_nvr_device); - device_add(&fdc_ps2_device); if (model == 2011) { - if (!strcmp("english_us", device_get_config_bios("bios_language"))) { - /* US English */ - rom_init(&ps->high_rom, - device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0), - 0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); + const device_t *d = device_context_get_device(); + const char * bios = device_get_config_bios("bios_language"); + const char * first = device_get_bios_file(d, bios, 0); + const char * second = device_get_bios_file(d, bios, 1); - } else if ((device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 1)) == NULL) { + if (!strcmp(bios, "english_us")) { + /* US English */ + rom_init(&ps->high_rom, first, + 0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); + } else if (second == NULL) { /* Combined ROM. */ - rom_init(&ps->high_rom, - device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0), + rom_init(&ps->high_rom, first, 0xf80000, 0x80000, 0x7ffff, 0, MEM_MAPPING_EXTERNAL); } else { /* Split ROM. */ - rom_init(&ps->mid_rom, - device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 0), + rom_init(&ps->mid_rom, first, 0xf80000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); - rom_init(&ps->high_rom, - device_get_bios_file(device_context_get_device(), device_get_config_bios("bios_language"), 1), + rom_init(&ps->high_rom, second, 0xfc0000, 0x40000, 0x3ffff, 0, MEM_MAPPING_EXTERNAL); } @@ -381,6 +379,8 @@ ps1_setup(int model) device_add(&ps1snd_device); } + + device_add(&ps_nvr_device); } static void From baae4c15d65404d7c70ff45ffdf19b8b0fdda2a4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 19 Feb 2025 12:58:40 +0100 Subject: [PATCH 76/82] Fixed a compile-breaking error in vid_p55da2.c as well. --- src/video/vid_ps55da2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index aaf5d4803..288aca027 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -872,7 +872,7 @@ da2_bitblt_exec(void *p) } da2->bitblt.destaddr += 2; break; - case DA2_BLT_CFILLTILE: + case DA2_BLT_CFILLTILE: { int32_t tileaddr = da2->bitblt.srcaddr + (da2->bitblt.y % da2->bitblt.tile_w) * 2; if (da2->bitblt.x >= da2->bitblt.size_x - 1) { DA2_CopyPlaneDataWithBitmask(tileaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); @@ -891,7 +891,7 @@ da2_bitblt_exec(void *p) } da2->bitblt.destaddr += 2; break; - case DA2_BLT_CCOPYF: + } case DA2_BLT_CCOPYF: if (da2->bitblt.x >= da2->bitblt.size_x - 1) { DA2_CopyPlaneDataWithBitmask(da2->bitblt.srcaddr, da2->bitblt.destaddr, da2->bitblt.maskr, da2); if (da2->bitblt.y >= da2->bitblt.size_y - 1) { From 71c9e694569fa09120f90ae069e5b3d538e94ffc Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 20 Feb 2025 15:35:56 +0100 Subject: [PATCH 77/82] Mach32 changes of the day (February 20th, 2025) 1. Actually fix the LFB access by subtracting the linear base address from the current address when LFB/MMIO is on. This fixes blankness of certain Mach32 drivers on Win3.1x. 2. Apply a minor but important fix to the fonts used by said Win3.1x driver when the dpconfig activates bit 2 without bit 12 set (e.g.: 0x2255), ergo, issuing host data as monochrome without swapping it. --- src/video/vid_ati_mach8.c | 70 +++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 06a60449f..71dd973da 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -336,7 +336,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } if ((dev->accel_bpp == 8) || (dev->accel_bpp == 15) || (dev->accel_bpp == 16) || (dev->accel_bpp == 24)) - mach_log("RdMask=%04x, DPCONFIG=%04x, Clipping: l=%d, r=%d, t=%d, b=%d, LineDrawOpt=%04x, BPP=%d, CMDType = %d, offs=%08x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, d(%d,%d), dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monpattern = %x.\n", + mach_log("RdMask=%04x, DPCONFIG=%04x, Clipping: l=%d, r=%d, t=%d, b=%d, LineDrawOpt=%04x, BPP=%d, CMDType = %d, offs=%08x, cnt = %d, input = %d, mono_src = %d, frgdsel = %d, d(%d,%d), dstxend = %d, pitch = %d, extcrt = %d, rw = %x, monopattern = %x.\n", dev->accel.rd_mask, mach->accel.dp_config, clip_l, clip_r, clip_t, clip_b, mach->accel.linedraw_opt, dev->accel_bpp, cmd_type, mach->accel.ge_offset, count, cpu_input, mono_src, frgd_sel, dev->accel.cur_x, dev->accel.cur_y, mach->accel.dest_x_end, dev->ext_pitch, dev->ext_crt_pitch, mach->accel.dp_config & 1, mach->accel.mono_pattern_enable); @@ -1039,7 +1039,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } break; case 2: - if (mach->accel.dp_config & 0x1000) { + if ((mach->accel.dp_config & 0x1000) || (mach->accel.dp_config & 0x04)) { mix = mix_dat >> 0x1f; mix_dat <<= 1; } else { @@ -2185,7 +2185,7 @@ mach_accel_out_pixtrans(svga_t *svga, mach_t *mach, ibm8514_t *dev, uint16_t val case 0x200: /*16-bit size*/ if (mono_src == 2) { if ((frgd_sel != 2) && (bkgd_sel != 2)) { - if ((mach->accel.dp_config & 0x1000) && !swap) { + if (((mach->accel.dp_config & 0x1000) && !swap) || swap) { mach_log("16-bit bus size swap.\n"); val = (val >> 8) | (val << 8); } @@ -5184,11 +5184,11 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = (addr - mach->linear_base) & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && - ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { + if ((addr - mach->linear_base) & 0x100) { mach_log("Port WORDB Write=%04x.\n", 0x02ee + (port_dword << 8)); mach_accel_outb(0x02ee + (addr & 1) + (port_dword << 8), val, mach); } else { @@ -5199,9 +5199,9 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) mach_log("Linear WORDB Write=%08x, val=%02x, ON=%x, dpconfig=%04x, apsize=%08x.\n", addr & dev->vram_mask, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); if (dev->on) - mach32_write_common(addr, val, 1, mach, svga); + mach32_write_common(addr - mach->linear_base, val, 1, mach, svga); else - svga_write_linear(addr, val, svga); + svga_write_linear(addr - mach->linear_base, val, svga); } } @@ -5211,11 +5211,11 @@ mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = (addr - mach->linear_base) & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && - ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { + if ((addr - mach->linear_base) & 0x100) { mach_log("Port WORDW Write=%04x.\n", 0x02ee + (port_dword << 8)); mach_accel_outw(0x02ee + (port_dword << 8), val, mach); } else { @@ -5224,11 +5224,11 @@ mach32_ap_writew(uint32_t addr, uint16_t val, void *priv) } } else { mach_log("Linear WORDW Write=%08x, val=%04x, ON=%x, dpconfig=%04x, apsize=%08x.\n", - addr & dev->vram_mask, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); + addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); if (dev->on) - mach32_writew_linear(addr, val, mach); + mach32_writew_linear(addr - mach->linear_base, val, mach); else - svga_writew_linear(addr, val, svga); + svga_writew_linear(addr - mach->linear_base, val, svga); } } @@ -5238,11 +5238,11 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) mach_t *mach = (mach_t *) priv; svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = (addr - mach->linear_base) & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && - ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { + if ((addr - mach->linear_base) & 0x100) { mach_log("Port WORDL Write=%04x.\n", 0x02ee + (port_dword << 8)); mach_accel_outw(0x02ee + (port_dword << 8), val & 0xffff, mach); mach_accel_outw(0x02ee + (port_dword << 8) + 4, val >> 16, mach); @@ -5253,11 +5253,11 @@ mach32_ap_writel(uint32_t addr, uint32_t val, void *priv) } } else { mach_log("Linear WORDL Write=%08x, val=%08x, ON=%x, dpconfig=%04x, apsize=%08x.\n", - addr & dev->vram_mask, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); + addr - mach->linear_base, val, dev->on, mach->accel.dp_config, mach->ap_size << 20); if (dev->on) - mach32_writel_linear(addr, val, mach); + mach32_writel_linear(addr - mach->linear_base, val, mach); else - svga_writel_linear(addr, val, svga); + svga_writel_linear(addr - mach->linear_base, val, svga); } } @@ -5268,19 +5268,19 @@ mach32_ap_readb(uint32_t addr, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t temp; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = (addr - mach->linear_base) & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && - ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { + if ((addr - mach->linear_base) & 0x100) temp = mach_accel_inb(0x02ee + (addr & 1) + (port_dword << 8), mach); else temp = mach_accel_inb(0x02e8 + (addr & 1) + (port_dword << 8), mach); } else { if (dev->on) - temp = mach32_read_common(addr, 1, mach, svga); + temp = mach32_read_common(addr - mach->linear_base, 1, mach, svga); else - temp = svga_read_linear(addr, svga); + temp = svga_read_linear(addr - mach->linear_base, svga); mach_log("Linear WORDB Read=%08x, ret=%02x, fast=%d.\n", addr, temp, svga->fast); } @@ -5295,19 +5295,19 @@ mach32_ap_readw(uint32_t addr, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint16_t temp; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = (addr - mach->linear_base) & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && - ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { + if ((addr - mach->linear_base) & 0x100) temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); else temp = mach_accel_inw(0x02e8 + (port_dword << 8), mach); } else { if (dev->on) - temp = mach32_readw_linear(addr, mach); + temp = mach32_readw_linear(addr - mach->linear_base, mach); else - temp = svga_readw_linear(addr, svga); + temp = svga_readw_linear(addr - mach->linear_base, svga); mach_log("Linear WORDW Read=%08x, ret=%04x.\n", addr, temp); } @@ -5322,11 +5322,11 @@ mach32_ap_readl(uint32_t addr, void *priv) svga_t *svga = &mach->svga; const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint32_t temp; - uint8_t port_dword = addr & 0xfc; + uint8_t port_dword = (addr - mach->linear_base) & 0xfc; if (((mach->local_cntl & 0x20) || (mach->pci_cntl_reg & 0x80)) && - ((addr >= ((mach->ap_size << 20) - 0x200)) && (addr < (mach->ap_size << 20)))) { - if (addr & 0x100) { + (((addr - mach->linear_base) >= ((mach->ap_size << 20) - 0x200)) && ((addr - mach->linear_base) < (mach->ap_size << 20)))) { + if ((addr - mach->linear_base) & 0x100) { temp = mach_accel_inw(0x02ee + (port_dword << 8), mach); temp |= (mach_accel_inw(0x02ee + (port_dword << 8) + 4, mach) << 8); } else { @@ -5335,9 +5335,9 @@ mach32_ap_readl(uint32_t addr, void *priv) } } else { if (dev->on) - temp = mach32_readl_linear(addr, mach); + temp = mach32_readl_linear(addr - mach->linear_base, mach); else - temp = svga_readl_linear(addr, svga); + temp = svga_readl_linear(addr - mach->linear_base, svga); mach_log("Linear WORDL Read=%08x, ret=%08x, ON%d.\n", addr, temp, dev->on); } From 6c933dd15719b3ba96f6f03f9a657a39ca6d8059 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Thu, 20 Feb 2025 18:24:38 -0300 Subject: [PATCH 78/82] Voodoo: Implement missing AGP CMDFIFO features Note that the reproduction cases for command 6 currently appear to be a result of CMDFIFO corruption instead of actual usage. --- src/include/86box/vid_voodoo_banshee.h | 1 + src/include/86box/vid_voodoo_common.h | 2 + src/video/vid_voodoo_banshee.c | 77 +++++++++++++++++++++++++- src/video/vid_voodoo_fifo.c | 77 ++++++++++++++++++++++++-- 4 files changed, 148 insertions(+), 9 deletions(-) diff --git a/src/include/86box/vid_voodoo_banshee.h b/src/include/86box/vid_voodoo_banshee.h index 89298e94e..257a549dd 100644 --- a/src/include/86box/vid_voodoo_banshee.h +++ b/src/include/86box/vid_voodoo_banshee.h @@ -18,6 +18,7 @@ #ifndef VIDEO_VOODOO_BANSHEE_H #define VIDEO_VOODOO_BANSHEE_H +void banshee_cmd_write(void *priv, uint32_t addr, uint32_t val); void banshee_set_overlay_addr(void *priv, uint32_t addr); #endif /*VIDEO_VOODOO_BANSHEE_H*/ diff --git a/src/include/86box/vid_voodoo_common.h b/src/include/86box/vid_voodoo_common.h index 5ab63ec3a..4201562c2 100644 --- a/src/include/86box/vid_voodoo_common.h +++ b/src/include/86box/vid_voodoo_common.h @@ -420,6 +420,7 @@ typedef struct voodoo_t { int cmdfifo_rp; int cmdfifo_ret_addr; int cmdfifo_in_sub; + int cmdfifo_in_agp; atomic_int cmdfifo_depth_rd; atomic_int cmdfifo_depth_wr; atomic_int cmdfifo_enabled; @@ -433,6 +434,7 @@ typedef struct voodoo_t { int cmdfifo_rp_2; int cmdfifo_ret_addr_2; int cmdfifo_in_sub_2; + int cmdfifo_in_agp_2; atomic_int cmdfifo_depth_rd_2; atomic_int cmdfifo_depth_wr_2; atomic_int cmdfifo_enabled_2; diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index fadd782a5..3727ccf8e 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -30,6 +30,7 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/mem.h> +#include <86box/dma.h> #include <86box/pci.h> #include <86box/rom.h> #include <86box/timer.h> @@ -43,9 +44,11 @@ #include <86box/vid_svga_render.h> #include <86box/vid_voodoo_common.h> #include <86box/vid_voodoo_display.h> +#include <86box/vid_voodoo_fb.h> #include <86box/vid_voodoo_fifo.h> #include <86box/vid_voodoo_regs.h> #include <86box/vid_voodoo_render.h> +#include <86box/vid_voodoo_texture.h> #define ROM_BANSHEE "roms/video/voodoo/Pci_sg.rom" #define ROM_CREATIVE_BANSHEE "roms/video/voodoo/BlasterPCI.rom" @@ -220,6 +223,7 @@ enum { Agp_agpHostAddressHigh = 0x08, Agp_agpGraphicsAddress = 0x0C, Agp_agpGraphicsStride = 0x10, + Agp_agpMoveCMD = 0x14, }; #define VGAINIT0_RAMDAC_8BIT (1 << 2) @@ -1365,6 +1369,10 @@ banshee_cmd_read(banshee_t *banshee, uint32_t addr) case cmdBaseSize0: ret = voodoo->cmdfifo_size; + if (voodoo->cmdfifo_enabled) + ret |= 0x100; + if (voodoo->cmdfifo_in_agp) + ret |= 0x200; break; case cmdBaseAddr1: @@ -1394,6 +1402,10 @@ banshee_cmd_read(banshee_t *banshee, uint32_t addr) case cmdBaseSize1: ret = voodoo->cmdfifo_size_2; + if (voodoo->cmdfifo_enabled_2) + ret |= 0x100; + if (voodoo->cmdfifo_in_agp_2) + ret |= 0x200; break; case 0x108: @@ -1613,10 +1625,11 @@ banshee_reg_writew(uint32_t addr, uint16_t val, void *priv) } } -static void -banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val) +void +banshee_cmd_write(void *priv, uint32_t addr, uint32_t val) { - voodoo_t *voodoo = banshee->voodoo; + banshee_t *banshee = (banshee_t *) priv; + voodoo_t *voodoo = banshee->voodoo; #if 0 banshee_log("banshee_cmd_write: addr=%03x val=%08x\n", addr & 0x1fc, val); #endif @@ -1641,6 +1654,62 @@ banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val) banshee->agpReqSize = val; break; + case Agp_agpMoveCMD: { + uint32_t src_addr = banshee->agpHostAddressLow; + uint32_t src_width = banshee->agpHostAddressHigh & 0x3fff; + uint32_t src_stride = (banshee->agpHostAddressHigh >> 14) & 0x3fff; + uint32_t src_end = src_addr + (banshee->agpReqSize & 0xfffff); /* don't know whether or not stride is accounted for! */ + uint32_t dest_addr = banshee->agpGraphicsAddress & 0x3ffffff; + uint32_t dest_stride = banshee->agpGraphicsStride & 0x7fff; +#if 0 + banshee_log("AGP: %d bytes W%d from %08x S%d to %d:%08x S%d\n", src_end - src_addr, src_width, src_addr, src_stride, (val >> 3) & 3, dest_addr, dest_stride); +#endif + switch ((val >> 3) & 3) { + case 0: /*Linear framebuffer (Banshee)*/ + case 1: /*Planar YUV*/ + if (voodoo->texture_present[0][(dest_addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) { +#if 0 + banshee_log("texture_present at %08x %i\n", dest_addr, (dest_addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); +#endif + flush_texture_cache(voodoo, dest_addr & voodoo->texture_mask, 0); + } + if (voodoo->texture_present[1][(dest_addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) { +#if 0 + banshee_log("texture_present at %08x %i\n", dest_addr, (dest_addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); +#endif + flush_texture_cache(voodoo, dest_addr & voodoo->texture_mask, 1); + } + while ((src_addr < src_end) && (dest_addr <= voodoo->fb_mask)) { + dma_bm_read(src_addr, &voodoo->fb_mem[dest_addr], MIN(src_width, voodoo->fb_mask - dest_addr), 4); + src_addr += src_stride; + dest_addr += dest_stride; + } + break; + case 2: /*Framebuffer*/ + src_width &= ~3; + while (src_addr < src_end) { + for (uint32_t i = 0; i < src_width; i += 4) + voodoo_fb_writel(dest_addr + i, mem_readl_phys(src_addr + i), voodoo); + src_addr += src_stride; + dest_addr += dest_stride; + } + break; + case 3: /*Texture*/ + src_width &= ~3; + while (src_addr < src_end) { + for (uint32_t i = 0; i < src_width; i += 4) + voodoo_tex_writel(dest_addr + i, mem_readl_phys(src_addr + i), voodoo); + src_addr += src_stride; + dest_addr += dest_stride; + } + break; + + default: + break; + } + break; + } + case cmdBaseAddr0: voodoo->cmdfifo_base = (val & 0xfff) << 12; voodoo->cmdfifo_end = voodoo->cmdfifo_base + (((voodoo->cmdfifo_size & 0xff) + 1) << 12); @@ -1655,6 +1724,7 @@ banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val) voodoo->cmdfifo_enabled = val & 0x100; if (!voodoo->cmdfifo_enabled) voodoo->cmdfifo_in_sub = 0; /*Not sure exactly when this should be reset*/ + voodoo->cmdfifo_in_agp = val & 0x200; #if 0 banshee_log("cmdfifo_base=%08x cmdfifo_end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); #endif @@ -1694,6 +1764,7 @@ banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val) voodoo->cmdfifo_enabled_2 = val & 0x100; if (!voodoo->cmdfifo_enabled_2) voodoo->cmdfifo_in_sub_2 = 0; /*Not sure exactly when this should be reset*/ + voodoo->cmdfifo_in_agp_2 = val & 0x200; #if 0 banshee_log("cmdfifo_base=%08x cmdfifo_end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); #endif diff --git a/src/video/vid_voodoo_fifo.c b/src/video/vid_voodoo_fifo.c index 54a0140f6..83be0f7bb 100644 --- a/src/video/vid_voodoo_fifo.c +++ b/src/video/vid_voodoo_fifo.c @@ -35,6 +35,7 @@ #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_voodoo_common.h> +#include <86box/vid_voodoo_banshee.h> #include <86box/vid_voodoo_banshee_blitter.h> #include <86box/vid_voodoo_fb.h> #include <86box/vid_voodoo_fifo.h> @@ -166,7 +167,10 @@ cmdfifo_get(voodoo_t *voodoo) } } - val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask]; + if (voodoo->cmdfifo_in_agp) + val = mem_readl_phys(voodoo->cmdfifo_rp); + else + val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask]; if (!voodoo->cmdfifo_in_sub) voodoo->cmdfifo_depth_rd++; @@ -200,7 +204,10 @@ cmdfifo_get_2(voodoo_t *voodoo) } } - val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp_2 & voodoo->fb_mask]; + if (voodoo->cmdfifo_in_agp_2) + val = mem_readl_phys(voodoo->cmdfifo_rp_2); + else + val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp_2 & voodoo->fb_mask]; if (!voodoo->cmdfifo_in_sub_2) voodoo->cmdfifo_depth_rd_2++; @@ -362,9 +369,21 @@ voodoo_fifo_thread(void *param) break; case 3: /*JMP local frame buffer*/ - voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc; + voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc; + voodoo->cmdfifo_in_agp = 0; #if 0 - voodoo_fifo_log("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header); + voodoo_fifo_log("JMP LFB to %08x %04x\n", voodoo->cmdfifo_rp, header); +#endif + break; + + case 4: /*JMP AGP*/ + if (UNLIKELY(voodoo->type < VOODOO_BANSHEE)) + fatal("CMDFIFO0: Not Banshee %08x\n", header); + + voodoo->cmdfifo_rp = ((header >> 4) & 0x1fffffc) | (cmdfifo_get(voodoo) << 25); + voodoo->cmdfifo_in_agp = 1; +#if 0 + voodoo_fifo_log("JMP AGP to %08x %04x\n", voodoo->cmdfifo_rp, header); #endif break; @@ -573,6 +592,23 @@ voodoo_fifo_thread(void *param) } break; + case 6: + if (UNLIKELY(voodoo->type < VOODOO_BANSHEE)) { + fatal("CMDFIFO6: Not Banshee %08x %08x\n", header, voodoo->cmdfifo_rp); + } else { + uint32_t val = cmdfifo_get(voodoo); + banshee_cmd_write(voodoo->priv, 0x00, val >> 5); /* agpReqSize */ + banshee_cmd_write(voodoo->priv, 0x04, cmdfifo_get(voodoo)); /* agpHostAddressLow */ + banshee_cmd_write(voodoo->priv, 0x08, cmdfifo_get(voodoo)); /* agpHostAddressHigh */ + banshee_cmd_write(voodoo->priv, 0x0c, cmdfifo_get(voodoo)); /* agpGraphicsAddress */ + banshee_cmd_write(voodoo->priv, 0x10, cmdfifo_get(voodoo)); /* agpGraphicsStride */ + banshee_cmd_write(voodoo->priv, 0x14, (val & 0x18) | 0x00); /* agpMoveCMD - start transfer */ +#if 0 + voodoo_fifo_log("CMDFIFO6 addr=%08x num=%i\n", addr, banshee->agpReqSize); +#endif + } + break; + default: fatal("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp); } @@ -624,9 +660,21 @@ voodoo_fifo_thread(void *param) break; case 3: /*JMP local frame buffer*/ - voodoo->cmdfifo_rp_2 = (header >> 4) & 0xfffffc; + voodoo->cmdfifo_rp_2 = (header >> 4) & 0xfffffc; + voodoo->cmdfifo_in_agp_2 = 0; #if 0 - voodoo_fifo_log("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header); + voodoo_fifo_log("JMP LFB to %08x %04x\n", voodoo->cmdfifo_rp_2, header); +#endif + break; + + case 4: /*JMP AGP*/ + if (UNLIKELY(voodoo->type < VOODOO_BANSHEE)) + fatal("CMDFIFO0: Not Banshee %08x\n", header); + + voodoo->cmdfifo_rp_2 = ((header >> 4) & 0x1fffffc) | (cmdfifo_get_2(voodoo) << 25); + voodoo->cmdfifo_in_agp_2 = 1; +#if 0 + voodoo_fifo_log("JMP AGP to %08x %04x\n", voodoo->cmdfifo_rp_2, header); #endif break; @@ -835,6 +883,23 @@ voodoo_fifo_thread(void *param) } break; + case 6: + if (UNLIKELY(voodoo->type < VOODOO_BANSHEE)) { + fatal("CMDFIFO6: Not Banshee %08x %08x\n", header, voodoo->cmdfifo_rp); + } else { + uint32_t val = cmdfifo_get_2(voodoo); + banshee_cmd_write(voodoo->priv, 0x00, val >> 5); /* agpReqSize */ + banshee_cmd_write(voodoo->priv, 0x04, cmdfifo_get_2(voodoo)); /* agpHostAddressLow */ + banshee_cmd_write(voodoo->priv, 0x08, cmdfifo_get_2(voodoo)); /* agpHostAddressHigh */ + banshee_cmd_write(voodoo->priv, 0x0c, cmdfifo_get_2(voodoo)); /* agpGraphicsAddress */ + banshee_cmd_write(voodoo->priv, 0x10, cmdfifo_get_2(voodoo)); /* agpGraphicsStride */ + banshee_cmd_write(voodoo->priv, 0x14, (val & 0x18) | 0x20); /* agpMoveCMD - start transfer */ +#if 0 + voodoo_fifo_log("CMDFIFO6 addr=%08x num=%i\n", addr, banshee->agpReqSize); +#endif + } + break; + default: fatal("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp); } From 67c02a53619d2bf1cfd4fa014925264fce675655 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Fri, 21 Feb 2025 00:32:15 +0100 Subject: [PATCH 79/82] Spock/Tribble (IBM PS/2 SCSI) changes of the late night (February 21st, 2025) 1. Made logs more consistent. 2. Actually add Write and Verify command, used by IBM OS/2 1.2 Extended, and fixes a hang by said OS after inserting disk 6. --- src/scsi/scsi_spock.c | 46 ++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index d6a26b7d0..567879a12 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -196,6 +196,7 @@ typedef struct { #define CMD_UNKNOWN_1C11 0x1c11 #define CMD_WRITE_DATA 0x1c02 #define CMD_VERIFY 0x1c03 +#define CMD_WRITE_VERIFY 0x1c04 #define IRQ_TYPE_NONE 0x0 #define IRQ_TYPE_SCB_COMPLETE 0x1 @@ -291,7 +292,7 @@ spock_write(uint16_t port, uint8_t val, void *priv) { spock_t *scsi = (spock_t *) priv; - spock_log("spock_write: port=%04x val=%02x %04x:%04x\n", port, val, CS, cpu_state.pc); + spock_log("spock_writeb: port=%04x, val=%02x, %04x:%04x.\n", port & 7, val, CS, cpu_state.pc); switch (port & 7) { case 0: @@ -332,6 +333,8 @@ spock_writew(uint16_t port, uint16_t val, void *priv) { spock_t *scsi = (spock_t *) priv; + spock_log("spock_writew: port=%04x, val=%04x, %04x:%04x.\n", port & 7, val, CS, cpu_state.pc); + switch (port & 7) { case 0: /*Command Interface Register*/ scsi->cir_pending[0] = val & 0xff; @@ -347,8 +350,6 @@ spock_writew(uint16_t port, uint16_t val, void *priv) default: break; } - - spock_log("spock_writew: port=%04x val=%04x\n", port, val); } static uint8_t @@ -390,7 +391,7 @@ spock_read(uint16_t port, void *priv) break; } - spock_log("spock_read: port=%04x val=%02x %04x(%05x):%04x.\n", port, temp, CS, cs, cpu_state.pc); + spock_log("spock_readb: port=%04x, val=%02x, %04x:%04x.\n", port & 7, temp, CS, cpu_state.pc); return temp; } @@ -412,7 +413,7 @@ spock_readw(uint16_t port, void *priv) break; } - spock_log("spock_readw: port=%04x val=%04x\n", port, temp); + spock_log("spock_readw: port=%04x, val=%04x, %04x:%04x.\n", port & 7, temp, CS, cpu_state.pc); return temp; } @@ -534,7 +535,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) int old_scb_state; if (scsi->in_reset) { - spock_log("Reset type = %d\n", scsi->in_reset); + spock_log("Reset type=%d\n", scsi->in_reset); scsi->status &= ~STATUS_BUSY; scsi->irq_status = 0; @@ -542,9 +543,8 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) for (c = 0; c < SCSI_ID_MAX; c++) spock_clear_irq(scsi, c); - if (scsi->in_reset == 1) { + if (scsi->in_reset == 1) scsi->basic_ctrl |= CTRL_IRQ_ENA; - } spock_set_irq(scsi, 0x0f, IRQ_TYPE_RESET_COMPLETE); @@ -585,6 +585,7 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) switch (scsi->scb_state) { case 0: /* Idle */ + spock_log("Start Idle.\n"); break; case 1: /* Select */ @@ -820,6 +821,28 @@ spock_execute_cmd(spock_t *scsi, scb_t *scb) scsi->scb_state = 2; return; + case CMD_WRITE_VERIFY: + if (scsi->present[scsi->scb_id] != 0xff) + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + else + scsi->cdb_id = 0xff; + + spock_log("Device Write with Verify\n"); + scsi->cdb[0] = GPCMD_WRITE_AND_VERIFY_10; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/ + scsi->cdb[3] = (scb->lba_addr >> 16) & 0xff; + scsi->cdb[4] = (scb->lba_addr >> 8) & 0xff; + scsi->cdb[5] = scb->lba_addr & 0xff; + scsi->cdb[6] = 0; /*Reserved*/ + scsi->cdb[7] = (scb->block_count >> 8) & 0xff; + scsi->cdb[8] = scb->block_count & 0xff; + scsi->cdb[9] = 0; /*Control*/ + scsi->cdb_len = 10; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + case CMD_REQUEST_SENSE: if (scsi->present[scsi->scb_id] != 0xff) scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; @@ -943,7 +966,7 @@ spock_process_scsi(spock_t *scsi, scb_t *scb) sd->buffer_length = spock_get_len(scsi, scb); scsi_device_command_phase0(sd, scsi->temp_cdb); - spock_log("SCSI ID %i: Current CDB[0] = %02x, LUN = %i, data len = %i, max len = %i, phase val = %02x\n", scsi->cdb_id, scsi->temp_cdb[0], scsi->temp_cdb[1] >> 5, sd->buffer_length, spock_get_len(scsi, scb), sd->phase); + spock_log("SCSI ID %i: Current CDB[0]=%02x, LUN=%i, buffer len=%i, max len=%i, phase val=%02x, data len=%d, enable bit 10=%03x\n", scsi->cdb_id, scsi->temp_cdb[0], scsi->temp_cdb[1] >> 5, sd->buffer_length, spock_get_len(scsi, scb), sd->phase, scsi->data_len, scb->enable & 0x400); if ((sd->phase != SCSI_PHASE_STATUS) && (sd->buffer_length > 0)) { p = scsi_device_get_callback(sd); @@ -1018,12 +1041,11 @@ spock_callback(void *priv) if (scsi->cmd_timer) { scsi->cmd_timer--; - if (!scsi->cmd_timer) { + if (!scsi->cmd_timer) spock_execute_cmd(scsi, scb); - } } - if (scsi->attention_wait && (scsi->scb_state == 0 || (scsi->attention_pending & 0xf0) == 0xe0)) { + if (scsi->attention_wait && ((scsi->scb_state == 0) || (scsi->attention_pending & 0xf0) == 0xe0)) { scsi->attention_wait--; if (!scsi->attention_wait) { scsi->attention = scsi->attention_pending; From 136183b998d127e4219d52e6e1f5bf81a5240adf Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 21 Feb 2025 01:43:22 +0100 Subject: [PATCH 80/82] MO and ZIP: Set phase data out on WRITE SAME command. --- src/disk/mo.c | 1 + src/disk/zip.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/disk/mo.c b/src/disk/mo.c index 5494fc9a8..7808e524e 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -1461,6 +1461,7 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb) break; case GPCMD_WRITE_SAME_10: + mo_set_phase(dev, SCSI_PHASE_DATA_OUT); alloc_length = 512; if ((cdb[1] & 6) == 6) diff --git a/src/disk/zip.c b/src/disk/zip.c index 72781281a..f579f23ec 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -1506,6 +1506,7 @@ zip_command(scsi_common_t *sc, const uint8_t *cdb) break; case GPCMD_WRITE_SAME_10: + zip_set_phase(dev, SCSI_PHASE_DATA_OUT); alloc_length = 512; if ((cdb[1] & 6) == 6) From 9801e8b1493754d9b22f5fa1c40c14151799bdc9 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 21 Feb 2025 19:37:53 +0100 Subject: [PATCH 81/82] IBM PS/55 Display Adapter II: Use calloc instead of malloc, fixes incorrect operation when heap protection is enabled. --- src/video/vid_ps55da2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 288aca027..f81a62ffe 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -3027,17 +3027,17 @@ da2_init(UNUSED(const device_t *info)) svga_t *mb_vga = svga_get_pri(); mb_vga->cable_connected = 0; - da2_t *da2 = malloc(sizeof(da2_t)); + da2_t *da2 = calloc(1, sizeof(da2_t)); da2->mb_vga = mb_vga; da2->dispontime = 1000ull << 32; da2->dispofftime = 1000ull << 32; int memsize = 1024 * 1024; - da2->vram = malloc(memsize); + da2->vram = calloc(1, memsize); da2->vram_mask = memsize - 1; - da2->cram = malloc(0x1000); + da2->cram = calloc(1, 0x1000); da2->vram_display_mask = DA2_MASK_CRAM; - da2->changedvram = malloc(/*(memsize >> 12) << 1*/ 0x1000000 >> 12); /* XX000h */ + da2->changedvram = calloc(1, /*(memsize >> 12) << 1*/ 0x1000000 >> 12); /* XX000h */ da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ da2->mmio.charset = device_get_config_int("charset"); From ce906664a51a1311f445536d8d0aa7270af410c1 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 21 Feb 2025 22:25:00 +0100 Subject: [PATCH 82/82] Device: increased the length of the temporary pbus string, should fix heap corruptions. --- src/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device.c b/src/device.c index 8b2ddf35e..434bd3776 100644 --- a/src/device.c +++ b/src/device.c @@ -490,7 +490,7 @@ device_get_name(const device_t *dev, int bus, char *name) const char *sbus = NULL; const char *fbus; char *tname; - char pbus[12] = { 0 }; + char pbus[16] = { 0 }; if (dev == NULL) return;