diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index 3c29a9265..9d2881294 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -86,15 +86,15 @@ #define ESDI_IOADDR_SEC 0x3518 #define ESDI_IRQCHAN 14 -#define BIOS_FILE_L "roms/hdd/esdi/90x8969.bin" -#define BIOS_FILE_H "roms/hdd/esdi/90x8970.bin" +#define BIOS_FILE_L "roms/hdd/esdi/62-000193-036.BIN" +#define BIOS_FILE_H "roms/hdd/esdi/62-000194-036.BIN" -#define ESDI_TIME (200*TIMER_USEC) +#define ESDI_TIME 512 #define CMD_ADAPTER 0 -typedef struct esdi_drive { +typedef struct esdi_drive_t { int spt, hpc; int tracks; int sectors; @@ -102,7 +102,7 @@ typedef struct esdi_drive { int hdd_num; } drive_t; -typedef struct esdi { +typedef struct esdi_t { int8_t dma; uint32_t bios; @@ -133,7 +133,7 @@ typedef struct esdi { int command; int cmd_state; - int in_reset; + int in_reset, in_reset2; uint64_t callback; pc_timer_t timer; @@ -240,10 +240,10 @@ esdi_mca_set_callback(esdi_t *dev, uint64_t callback) if (callback) { dev->callback = callback; - timer_set_delay_u64(&dev->timer, dev->callback); + timer_on_auto(&dev->timer, dev->callback); } else { dev->callback = 0; - timer_disable(&dev->timer); + timer_stop(&dev->timer); } } @@ -824,11 +824,18 @@ esdi_read(uint16_t port, void *priv) uint8_t ret = 0xff; switch (port & 7) { - case 2: /*Basic status register*/ + case 2: /*Basic status register*/ + if (!dev->status) { + if (((dev->command == CMD_WRITE) || dev->in_reset2) && !dev->cmd_dev) { + dev->in_reset2 = 0; + dev->status |= STATUS_STATUS_OUT_FULL; + } else if (dev->command && (dev->cmd_dev == ATTN_HOST_ADAPTER)) + dev->status |= STATUS_STATUS_OUT_FULL; + } ret = dev->status; break; - case 3: /*IRQ status*/ + case 3: /*IRQ status*/ dev->status &= ~STATUS_IRQ; ret = dev->irq_status; break; @@ -852,6 +859,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) case 2: /*Basic control register*/ if ((dev->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) { dev->in_reset = 1; + dev->in_reset2 = 1; esdi_mca_set_callback(dev, ESDI_TIME * 50); dev->status = STATUS_BUSY; } @@ -883,6 +891,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) case ATTN_RESET: dev->in_reset = 1; + dev->in_reset2 = 1; esdi_mca_set_callback(dev, ESDI_TIME * 50); dev->status = STATUS_BUSY; break; @@ -1143,6 +1152,7 @@ esdi_init(const device_t *info) /* Mark for a reset. */ dev->in_reset = 1; + dev->in_reset2 = 1; esdi_mca_set_callback(dev, ESDI_TIME * 50); dev->status = STATUS_BUSY; diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index f80662c82..a4a9f2ddc 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -220,7 +220,7 @@ ide_get_drive(int ch) double -ide_get_period(ide_t *ide, int size) +ide_get_xfer_time(ide_t *ide, int size) { double period = (10.0 / 3.0); @@ -313,7 +313,7 @@ ide_atapi_get_period(uint8_t channel) return -1.0; } - return ide_get_period(ide, 1); + return ide_get_xfer_time(ide, 1); } @@ -535,7 +535,7 @@ static void ide_hd_identify(ide_t *ide) ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ ide->buffer[0] = (1 << 6); /*Fixed drive*/ ide->buffer[20] = 3; /*Buffer type*/ - ide->buffer[21] = 512; /*Buffer size*/ + ide->buffer[21] = hdd[ide->hdd_num].cache.num_segments * hdd[ide->hdd_num].cache.segment_size; /*Buffer size*/ ide->buffer[50] = 0x4000; /* Capabilities */ ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0; @@ -577,12 +577,11 @@ static void ide_hd_identify(ide_t *ide) ide_log("Current CHS translation: %i, %i, %i\n", ide->buffer[54], ide->buffer[55], ide->buffer[56]); } + ide->buffer[47] = hdd[ide->hdd_num].max_multiple_block | 0x8000; /*Max sectors on multiple transfer command*/ if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board]) { - ide->buffer[47] = 32 | 0x8000; /*Max sectors on multiple transfer command*/ ide->buffer[80] = 0x7e; /*ATA-1 to ATA-6 supported*/ ide->buffer[81] = 0x19; /*ATA-6 revision 3a supported*/ } else { - ide->buffer[47] = 16 | 0x8000; /*Max sectors on multiple transfer command*/ ide->buffer[80] = 0x0e; /*ATA-1 to ATA-3 supported*/ } } @@ -692,13 +691,15 @@ ide_get_sector(ide_t *ide) uint32_t heads, sectors; if (ide->lba) - return (off64_t)ide->lba_addr + ide->skip512; + return (off64_t)ide->lba_addr; else { heads = ide->cfg_hpc; sectors = ide->cfg_spt; + uint8_t sector = ide->sector ? ide->sector : 1; + return ((((off64_t) ide->cylinder * heads) + ide->head) * - sectors) + (ide->sector - 1) + ide->skip512; + sectors) + (sector - 1); } } @@ -733,6 +734,8 @@ loadhd(ide_t *ide, int d, const char *fn) return; } + hdd_preset_auto(&hdd[d]); + ide->spt = ide->cfg_spt = hdd[d].spt; ide->hpc = ide->cfg_hpc = hdd[d].hpc; ide->tracks = hdd[d].tracks; @@ -1226,31 +1229,41 @@ ide_write_data(ide_t *ide, uint32_t val, int length) if (ide->type == IDE_ATAPI) ide_atapi_packet_write(ide, val, length); } else { - switch(length) { - case 1: - idebufferb[ide->pos] = val & 0xff; - ide->pos++; - break; - case 2: - idebufferw[ide->pos >> 1] = val & 0xffff; - ide->pos += 2; - break; - case 4: - idebufferl[ide->pos >> 2] = val; - ide->pos += 4; - break; - default: - return; - } + switch(length) { + case 1: + idebufferb[ide->pos] = val & 0xff; + ide->pos++; + break; + case 2: + idebufferw[ide->pos >> 1] = val & 0xffff; + ide->pos += 2; + break; + case 4: + idebufferl[ide->pos >> 2] = val; + ide->pos += 4; + break; + default: + return; + } - if (ide->pos >= 512) { - ide->pos=0; - ide->atastat = BSY_STAT; - if (ide->command == WIN_WRITE_MULTIPLE) - ide_callback(ide); - else - ide_set_callback(ide, ide_get_period(ide, 512)); - } + if (ide->pos >= 512) { + ide->pos=0; + ide->atastat = BSY_STAT; + double seek_time = hdd_timing_write(&hdd[ide->hdd_num], ide_get_sector(ide), 1); + double xfer_time = ide_get_xfer_time(ide, 512); + double wait_time = seek_time + xfer_time; + if (ide->command == WIN_WRITE_MULTIPLE) { + if ((ide->blockcount+1) >= ide->blocksize || ide->secount == 1) { + ide_set_callback(ide, seek_time + xfer_time + ide->pending_delay); + ide->pending_delay = 0; + } else { + ide->pending_delay += wait_time; + ide_callback(ide); + } + } else { + ide_set_callback(ide, wait_time); + } + } } } @@ -1601,9 +1614,13 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) else ide->atastat = READY_STAT | BSY_STAT; - if (ide->type == IDE_ATAPI) + if (ide->type == IDE_ATAPI) { ide->sc->callback = 100.0 * IDE_TIME; - ide_set_callback(ide, 100.0 * IDE_TIME); + ide_set_callback(ide, 100.0 * IDE_TIME); + } else { + double seek_time = hdd_seek_get_time(&hdd[ide->hdd_num], ide_get_sector(ide), HDD_OP_SEEK, 0, 0.0); + ide_set_callback(ide, seek_time); + } return; } @@ -1641,15 +1658,26 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide->atastat = BSY_STAT; if (ide->type == IDE_HDD) { + uint32_t sec_count; + double wait_time; if ((val == WIN_READ_DMA) || (val == WIN_READ_DMA_ALT)) { - if (ide->secount) - ide_set_callback(ide, ide_get_period(ide, (int) ide->secount << 9)); - else - ide_set_callback(ide, ide_get_period(ide, 131072)); - } else if (val == WIN_READ_MULTIPLE) - ide_set_callback(ide, 200.0 * IDE_TIME); - else - ide_set_callback(ide, ide_get_period(ide, 512)); + // TODO make DMA timing more accurate + sec_count = ide->secount ? ide->secount : 256; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count); + double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); + wait_time = seek_time > xfer_time ? seek_time : xfer_time; + } else if (val == WIN_READ_MULTIPLE) { + sec_count = (ide->secount < ide->blocksize) ? ide->secount : ide->blocksize; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count); + double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); + wait_time = seek_time + xfer_time; + } else { + sec_count = 1; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count); + double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); + wait_time = seek_time + xfer_time; + } + ide_set_callback(ide, wait_time); } else ide_set_callback(ide, 200.0 * IDE_TIME); ide->do_initial_read = 1; @@ -1690,14 +1718,16 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) if ((ide->type == IDE_HDD) && ((val == WIN_WRITE_DMA) || (val == WIN_WRITE_DMA_ALT))) { - if (ide->secount) - ide_set_callback(ide, ide_get_period(ide, (int) ide->secount << 9)); - else - ide_set_callback(ide, ide_get_period(ide, 131072)); + uint32_t sec_count = ide->secount ? ide->secount : 256; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count); + double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); + double wait_time = seek_time > xfer_time ? seek_time : xfer_time; + ide_set_callback(ide, wait_time); } else if ((ide->type == IDE_HDD) && - ((val == WIN_VERIFY) || (val == WIN_VERIFY_ONCE))) - ide_set_callback(ide, ide_get_period(ide, 512)); - else if (val == WIN_IDENTIFY) + ((val == WIN_VERIFY) || (val == WIN_VERIFY_ONCE))) { + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), ide->secount); + ide_set_callback(ide, seek_time + ide_get_xfer_time(ide, 2)); + } else if (val == WIN_IDENTIFY) ide_callback(ide); else ide_set_callback(ide, 200.0 * IDE_TIME); @@ -1864,10 +1894,20 @@ ide_read_data(ide_t *ide, int length) if (ide->secount) { ide_next_sector(ide); ide->atastat = BSY_STAT | READY_STAT | DSC_STAT; - if (ide->command == WIN_READ_MULTIPLE) - ide_callback(ide); - else - ide_set_callback(ide, ide_get_period(ide, 512)); + if (ide->command == WIN_READ_MULTIPLE) { + if (!ide->blockcount) { + uint32_t sec_count = (ide->secount < ide->blocksize) ? ide->secount : ide->blocksize; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count); + double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); + ide_set_callback(ide, seek_time + xfer_time); + } else { + ide_callback(ide); + } + } else { + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), 1); + double xfer_time = ide_get_xfer_time(ide, 512); + ide_set_callback(ide, seek_time + xfer_time); + } } else if (ide->command != WIN_READ_MULTIPLE) ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); } diff --git a/src/disk/hdd.c b/src/disk/hdd.c index c2d619062..1b63a83e9 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -17,15 +17,19 @@ * Copyright 2017-2019 Fred N. van Kempen. */ #include -#include +#include #include +#include +#include +#include #include #include <86box/86box.h> #include <86box/plat.h> #include <86box/ui.h> #include <86box/hdd.h> #include <86box/cdrom.h> - +#include <86box/video.h> +#include "cpu.h" hard_disk_t hdd[HDD_NUM]; @@ -150,3 +154,346 @@ hdd_is_valid(int c) return(1); } + +double +hdd_seek_get_time(hard_disk_t *hdd, uint32_t dst_addr, uint8_t operation, uint8_t continuous, double max_seek_time) +{ + hdd_zone_t *zone = NULL; + for (int i = 0; i < hdd->num_zones; i++) { + zone = &hdd->zones[i]; + if (zone->end_sector >= dst_addr) + break; + } + + uint32_t new_track = zone->start_track + ((dst_addr - zone->start_sector) / zone->sectors_per_track); + uint32_t new_cylinder = new_track / hdd->phy_heads; + uint32_t cylinder_diff = abs((int)hdd->cur_cylinder - (int)new_cylinder); + + bool sequential = dst_addr == hdd->cur_addr + 1; + continuous = continuous && sequential; + + double seek_time = 0.0; + if (continuous) { + if (new_track == hdd->cur_track) { + // Same track + seek_time = zone->sector_time_usec; + } else if (!cylinder_diff) { + // Same cylinder, sequential track + seek_time = hdd->head_switch_usec; + } else { + // Sequential cylinder + seek_time = hdd->cyl_switch_usec; + } + } else { + if (!cylinder_diff) { + if (operation != HDD_OP_SEEK) { + seek_time = hdd->avg_rotation_lat_usec; + } else { + //seek_time = hdd->cyl_switch_usec; + seek_time = 50.0; + } + } else { + seek_time = hdd->cyl_switch_usec + (hdd->full_stroke_usec * (double)cylinder_diff / (double)hdd->phy_cyl); + if (operation != HDD_OP_SEEK) { + seek_time += hdd->avg_rotation_lat_usec; + } + } + } + + if (!max_seek_time || seek_time <= max_seek_time) { + hdd->cur_addr = dst_addr; + hdd->cur_track = new_track; + hdd->cur_cylinder = new_cylinder; + } + + return seek_time; +} + +static void +hdd_readahead_update(hard_disk_t *hdd) +{ + hdd_cache_t *cache = &hdd->cache; + if (cache->ra_ongoing) { + hdd_cache_seg_t *segment = &cache->segments[cache->ra_segment]; + + uint64_t elapsed_cycles = tsc - cache->ra_start_time; + double elapsed_us = (double)elapsed_cycles / cpuclock * 1000000.0; + // Do not overwrite data not yet read by host + uint32_t max_read_ahead = (segment->host_addr + cache->segment_size) - segment->ra_addr; + + double seek_time = 0.0; + + for (uint32_t i = 0; i < max_read_ahead; i++) { + seek_time += hdd_seek_get_time(hdd, segment->ra_addr, HDD_OP_READ, 1, elapsed_us - seek_time); + if (seek_time > elapsed_us) + break; + + segment->ra_addr++; + } + + if (segment->ra_addr > segment->lba_addr + cache->segment_size) { + uint32_t space_needed = segment->ra_addr - (segment->lba_addr + cache->segment_size); + segment->lba_addr += space_needed; + } + } +} + +static double +hdd_writecache_flush(hard_disk_t *hdd) +{ + double seek_time = 0.0; + while (hdd->cache.write_pending) { + seek_time += hdd_seek_get_time(hdd, hdd->cache.write_addr, HDD_OP_WRITE, 1, 0); + hdd->cache.write_addr++; + hdd->cache.write_pending--; + } + + return seek_time; +} + +static void +hdd_writecache_update(hard_disk_t *hdd) +{ + if (hdd->cache.write_pending) { + uint64_t elapsed_cycles = tsc - hdd->cache.write_start_time; + double elapsed_us = (double)elapsed_cycles / cpuclock * 1000000.0; + double seek_time = 0.0; + + while (hdd->cache.write_pending) { + seek_time += hdd_seek_get_time(hdd, hdd->cache.write_addr, HDD_OP_WRITE, 1, elapsed_us - seek_time); + if (seek_time > elapsed_us) + break; + + hdd->cache.write_addr++; + hdd->cache.write_pending--; + } + } +} + +double +hdd_timing_write(hard_disk_t *hdd, uint32_t addr, uint32_t len) +{ + hdd_readahead_update(hdd); + hdd_writecache_update(hdd); + + hdd->cache.ra_ongoing = 0; + + double seek_time = 0.0; + + if (hdd->cache.write_pending && (addr != (hdd->cache.write_addr + hdd->cache.write_pending))) { + // New request is not sequential to existing cache, need to flush it + seek_time += hdd_writecache_flush(hdd); + } + + if (!hdd->cache.write_pending) { + // Cache is empty + hdd->cache.write_addr = addr; + } + + hdd->cache.write_pending += len; + if (hdd->cache.write_pending > hdd->cache.write_size) { + // If request is bigger than free cache, flush some data first + uint32_t flush_needed = hdd->cache.write_pending - hdd->cache.write_size; + for (uint32_t i = 0; i < flush_needed; i++) { + seek_time += hdd_seek_get_time(hdd, hdd->cache.write_addr, HDD_OP_WRITE, 1, 0); + hdd->cache.write_addr++; + } + } + + hdd->cache.write_start_time = tsc + (uint32_t)(seek_time * cpuclock / 1000000.0); + + return seek_time; +} + +double +hdd_timing_read(hard_disk_t *hdd, uint32_t addr, uint32_t len) +{ + hdd_readahead_update(hdd); + hdd_writecache_update(hdd); + + double seek_time = 0.0; + seek_time += hdd_writecache_flush(hdd); + + hdd_cache_t *cache = &hdd->cache; + hdd_cache_seg_t *active_seg = &cache->segments[0]; + + for (uint32_t i = 0; i < cache->num_segments; i++) { + hdd_cache_seg_t *segment = &cache->segments[i]; + if (!segment->valid) { + active_seg = segment; + continue; + } + + if (segment->lba_addr <= addr && (segment->lba_addr + cache->segment_size) >= addr) { + // Cache HIT + segment->host_addr = addr; + active_seg = segment; + if (addr + len > segment->ra_addr) { + uint32_t need_read = (addr + len) - segment->ra_addr; + for (uint32_t j = 0; j < need_read; j++) { + seek_time += hdd_seek_get_time(hdd, segment->ra_addr, HDD_OP_READ, 1, 0.0); + segment->ra_addr++; + } + } + if (addr + len > segment->lba_addr + cache->segment_size) { + // Need to erase some previously cached data + uint32_t space_needed = (addr + len) - (segment->lba_addr + cache->segment_size); + segment->lba_addr += space_needed; + } + goto update_lru; + } else { + if (segment->lru > active_seg->lru) { + active_seg = segment; + } + } + } + + // Cache MISS + active_seg->lba_addr = addr; + active_seg->valid = 1; + active_seg->host_addr = addr; + active_seg->ra_addr = addr; + + for (uint32_t i = 0; i < len; i++) { + seek_time += hdd_seek_get_time(hdd, active_seg->ra_addr, HDD_OP_READ, i != 0, 0.0); + active_seg->ra_addr++; + } + +update_lru: + for (uint32_t i = 0; i < cache->num_segments; i++) { + cache->segments[i].lru++; + } + + active_seg->lru = 0; + + cache->ra_ongoing = 1; + cache->ra_segment = active_seg->id; + cache->ra_start_time = tsc + (uint32_t)(seek_time * cpuclock / 1000000.0); + + return seek_time; +} + +static void +hdd_cache_init(hard_disk_t *hdd) +{ + hdd_cache_t *cache = &hdd->cache; + cache->ra_segment = 0; + cache->ra_ongoing = 0; + cache->ra_start_time = 0; + + for (uint32_t i = 0; i < cache->num_segments; i++) { + cache->segments[i].valid = 0; + cache->segments[i].lru = 0; + cache->segments[i].id = i; + cache->segments[i].ra_addr = 0; + cache->segments[i].host_addr = 0; + } +} + +static void +hdd_zones_init(hard_disk_t *hdd) +{ + uint32_t lba = 0; + uint32_t track = 0; + + double revolution_usec = 60.0 / (double)hdd->rpm * 1000000.0; + for (uint32_t i = 0; i < hdd->num_zones; i++) { + hdd_zone_t *zone = &hdd->zones[i]; + zone->start_sector = lba; + zone->start_track = track; + zone->sector_time_usec = revolution_usec / (double)zone->sectors_per_track; + uint32_t tracks = zone->cylinders * hdd->phy_heads; + lba += tracks * zone->sectors_per_track; + zone->end_sector = lba - 1; + track += tracks - 1; + } +} + +hdd_preset_t hdd_presets[] = { + { .target_year = 1989, .match_max_mbyte = 99, .zones = 1, .avg_spt = 35, .heads = 2, .rpm = 3500, .full_stroke_ms = 40, .track_seek_ms = 8, + .rcache_num_seg = 1, .rcache_seg_size = 16, .max_multiple = 8 }, + + { .target_year = 1992, .match_max_mbyte = 249, .zones = 1, .avg_spt = 45, .heads = 2, .rpm = 3500, .full_stroke_ms = 30, .track_seek_ms = 6, + .rcache_num_seg = 4, .rcache_seg_size = 16, .max_multiple = 8 }, + + { .target_year = 1994, .match_max_mbyte = 999, .zones = 8, .avg_spt = 80, .heads = 4, .rpm = 4500, .full_stroke_ms = 26, .track_seek_ms = 5, + .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 16 }, + + { .target_year = 1996, .match_max_mbyte = 1999, .zones = 16, .avg_spt = 135, .heads = 4, .rpm = 5400, .full_stroke_ms = 24, .track_seek_ms = 3, + .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, + + { .target_year = 1997, .match_max_mbyte = 4999, .zones = 16, .avg_spt = 185, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.5, + .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 32 }, + + { .target_year = 1998, .match_max_mbyte = 9999, .zones = 16, .avg_spt = 300, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, + .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 32 }, + + { .target_year = 2000, .match_max_mbyte = 99999, .zones = 16, .avg_spt = 350, .heads = 6, .rpm = 7200, .full_stroke_ms = 15, .track_seek_ms = 2, + .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 32 }, +}; + +void +hdd_preset_apply(hard_disk_t *hdd, hdd_preset_t *preset) +{ + hdd->phy_heads = preset->heads; + hdd->rpm = preset->rpm; + + double revolution_usec = 60.0 / (double)hdd->rpm * 1000000.0; + hdd->avg_rotation_lat_usec = revolution_usec / 2; + hdd->full_stroke_usec = preset->full_stroke_ms * 1000; + hdd->head_switch_usec = preset->track_seek_ms * 1000; + hdd->cyl_switch_usec = preset->track_seek_ms * 1000; + + hdd->cache.num_segments = preset->rcache_num_seg; + hdd->cache.segment_size = preset->rcache_seg_size; + hdd->max_multiple_block = preset->max_multiple; + + hdd->cache.write_size = 64; + + hdd->num_zones = preset->zones; + + uint32_t disk_sectors = hdd->tracks * hdd->hpc * hdd->spt; + uint32_t sectors_per_surface = (uint32_t)ceil((double)disk_sectors / (double)hdd->phy_heads); + uint32_t cylinders = (uint32_t)ceil((double)sectors_per_surface / (double)preset->avg_spt); + hdd->phy_cyl = cylinders; + uint32_t cylinders_per_zone = cylinders / preset->zones; + + uint32_t total_sectors = 0; + for (uint32_t i = 0; i < preset->zones; i++) { + uint32_t spt; + double zone_percent = i * 100 / (double)preset->zones; + + if (i < preset->zones - 1) { + // Function for realistic zone sector density + double spt_percent = -0.00341684 * pow(zone_percent, 2) - 0.175811 * zone_percent + 118.48; + spt = (uint32_t)ceil((double)preset->avg_spt * spt_percent / 100); + } else { + spt = (uint32_t)ceil((double)(disk_sectors - total_sectors) / (double)(cylinders_per_zone*preset->heads)); + } + + uint32_t zone_sectors = spt * cylinders_per_zone * preset->heads; + total_sectors += zone_sectors; + + hdd->zones[i].cylinders = cylinders_per_zone; + hdd->zones[i].sectors_per_track = spt; + } + + hdd_zones_init(hdd); + hdd_cache_init(hdd); +} + +void +hdd_preset_auto(hard_disk_t *hdd) +{ + uint32_t disk_sectors = hdd->tracks * hdd->hpc * hdd->spt; + uint32_t disk_size_mb = disk_sectors * 512 / 1024 / 1024; + int i; + for (i = 0; i < (sizeof(hdd_presets) / sizeof(hdd_presets[0])); i++) { + if (hdd_presets[i].match_max_mbyte >= disk_size_mb) + break; + } + + hdd_preset_t *preset = &hdd_presets[i]; + + hdd_preset_apply(hdd, preset); +} \ No newline at end of file diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index 8f1b3551a..840e5daad 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -49,7 +49,7 @@ typedef struct ide_s { blocksize, blockcount, hdd_num, channel, pos, sector_pos, - lba, skip512, + lba, reset, mdma_mode, do_initial_read; uint32_t secount, sector, @@ -67,6 +67,7 @@ typedef struct ide_s { /* Stuff mostly used by ATAPI */ scsi_common_t *sc; int interrupt_drq; + double pending_delay; int (*get_max)(int ide_has_dma, int type); int (*get_timings)(int ide_has_dma, int type); diff --git a/src/include/86box/hdd.h b/src/include/86box/hdd.h index 96afcdde0..2a2a16bfc 100644 --- a/src/include/86box/hdd.h +++ b/src/include/86box/hdd.h @@ -72,6 +72,62 @@ enum { }; #endif +enum { + HDD_OP_SEEK = 0, + HDD_OP_READ, + HDD_OP_WRITE +}; + +#define HDD_MAX_ZONES 16 +#define HDD_MAX_CACHE_SEG 16 + +typedef struct { + uint32_t match_max_mbyte; + uint32_t zones; + uint32_t avg_spt; + uint32_t heads; + uint32_t rpm; + uint32_t target_year; + uint32_t rcache_num_seg; + uint32_t rcache_seg_size; + uint32_t max_multiple; + double full_stroke_ms; + double track_seek_ms; +} hdd_preset_t; + +typedef struct { + uint32_t id; + uint32_t lba_addr; + uint32_t ra_addr; + uint32_t host_addr; + uint8_t lru; + uint8_t valid; +} hdd_cache_seg_t; + +typedef struct { + // Read cache + hdd_cache_seg_t segments[HDD_MAX_CACHE_SEG]; + uint32_t num_segments; + uint32_t segment_size; + uint32_t ra_segment; + uint8_t ra_ongoing; + uint64_t ra_start_time; + + // Write cache + uint32_t write_addr; + uint32_t write_pending; + uint32_t write_size; + uint64_t write_start_time; +} hdd_cache_t; + +typedef struct { + uint32_t cylinders; + uint32_t sectors_per_track; + double sector_time_usec; + uint32_t start_sector; + uint32_t end_sector; + uint32_t start_track; +} hdd_zone_t; /* Define the virtual Hard Disk. */ typedef struct { @@ -100,6 +156,23 @@ typedef struct { spt, hpc, /* Physical geometry parameters */ tracks; + + hdd_zone_t zones[HDD_MAX_ZONES]; + uint32_t num_zones; + hdd_cache_t cache; + uint32_t phy_cyl; + uint32_t phy_heads; + uint32_t rpm; + uint8_t max_multiple_block; + + uint32_t cur_cylinder; + uint32_t cur_track; + uint32_t cur_addr; + + double avg_rotation_lat_usec; + double full_stroke_usec; + double head_switch_usec; + double cyl_switch_usec; } hard_disk_t; @@ -131,5 +204,10 @@ extern int image_is_hdi(const char *s); extern int image_is_hdx(const char *s, int check_signature); extern int image_is_vhd(const char *s, int check_signature); +extern double hdd_timing_write(hard_disk_t *hdd, uint32_t addr, uint32_t len); +extern double hdd_timing_read(hard_disk_t *hdd, uint32_t addr, uint32_t len); +extern double hdd_seek_get_time(hard_disk_t *hdd, uint32_t dst_addr, uint8_t operation, uint8_t continuous, double max_seek_time); +extern void hdd_preset_apply(hard_disk_t *hdd, hdd_preset_t *preset); +extern void hdd_preset_auto(hard_disk_t *hdd); #endif /*EMU_HDD_H*/ diff --git a/src/include/86box/resource.h b/src/include/86box/resource.h index cd4eb1f83..75d056ea1 100644 --- a/src/include/86box/resource.h +++ b/src/include/86box/resource.h @@ -18,6 +18,7 @@ * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. * Copyright 2018,2019 David Hrdlička. + * Copyright 2021-2022 Jasmine Iwanek. */ #ifndef WIN_RESOURCE_H @@ -184,6 +185,8 @@ #define IDC_CHECK_VOODOO 1022 #define IDC_BUTTON_VOODOO 1023 #define IDC_CHECK_IBM8514 1024 +#define IDC_CHECK_XGA 1025 +#define IDC_BUTTON_XGA 1026 #define IDC_INPUT 1030 /* input config */ #define IDC_COMBO_MOUSE 1031 diff --git a/src/include/86box/scsi_ncr5380.h b/src/include/86box/scsi_ncr5380.h index 6053e0275..5f6ded14b 100644 --- a/src/include/86box/scsi_ncr5380.h +++ b/src/include/86box/scsi_ncr5380.h @@ -26,6 +26,7 @@ extern const device_t scsi_lcs6821n_device; extern const device_t scsi_rt1000b_device; +extern const device_t scsi_rt1000mc_device; extern const device_t scsi_t128_device; extern const device_t scsi_t130b_device; extern const device_t scsi_ls2000_device; diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 0bb1e85cd..a9816ac4a 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -62,7 +62,7 @@ typedef struct ibm8514_t int x1, x2, y1, y2; int sys_cnt, sys_cnt2; int temp_cnt; - int16_t cx, cy; + int16_t cx, cy, oldcy; int16_t sx, sy; int16_t dx, dy; int16_t err; @@ -80,7 +80,7 @@ typedef struct ibm8514_t int odd_in, odd_out; uint16_t scratch; - int fill_state, fill_drop; + int fill_state, xdir, ydir; } accel; uint16_t test; diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index aa0f874fd..cfaad4481 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -38,6 +38,7 @@ extern "C" { #include <86box/config.h> #include <86box/keyboard.h> #include <86box/plat.h> +#include <86box/ui.h> #include <86box/discord.h> #include <86box/video.h> #include <86box/machine.h> @@ -1524,18 +1525,25 @@ void MainWindow::refreshMediaMenu() { ui->actionMCA_devices->setVisible(machine_has_bus(machine, MACHINE_BUS_MCA)); } -void MainWindow::showMessage(const QString& header, const QString& message) { +void MainWindow::showMessage(int flags, const QString& header, const QString& message) { if (QThread::currentThread() == this->thread()) { - showMessage_(header, message); + showMessage_(flags, header, message); } else { - emit showMessageForNonQtThread(header, message); + emit showMessageForNonQtThread(flags, header, message); } } -void MainWindow::showMessage_(const QString &header, const QString &message) { +void MainWindow::showMessage_(int flags, const QString &header, const QString &message) { QMessageBox box(QMessageBox::Warning, header, message, QMessageBox::NoButton, this); + if (flags & (MBX_FATAL)) { + box.setIcon(QMessageBox::Critical); + } + else if (!(flags & (MBX_ERROR | MBX_WARNING))) { + box.setIcon(QMessageBox::Warning); + } box.setTextFormat(Qt::TextFormat::RichText); box.exec(); + if (cpu_thread_run == 0) QApplication::exit(-1); } void MainWindow::keyPressEvent(QKeyEvent* event) diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 37468c413..30163429a 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -25,7 +25,7 @@ public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); - void showMessage(const QString& header, const QString& message); + void showMessage(int flags, const QString& header, const QString& message); void getTitle(wchar_t* title); void blitToWidget(int x, int y, int w, int h, int monitor_index); QSize getRenderWidgetSize(); @@ -51,7 +51,7 @@ signals: void setFullscreen(bool state); void setMouseCapture(bool state); - void showMessageForNonQtThread(const QString& header, const QString& message); + void showMessageForNonQtThread(int flags, const QString& header, const QString& message); void getTitleForNonQtThread(wchar_t* title); public slots: void showSettings(); @@ -108,7 +108,7 @@ private slots: void on_actionRenderer_options_triggered(); void refreshMediaMenu(); - void showMessage_(const QString& header, const QString& message); + void showMessage_(int flags, const QString& header, const QString& message); void getTitle_(wchar_t* title); void on_actionMCA_devices_triggered(); diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 42d839ecf..3f323b12f 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -326,7 +326,7 @@ void plat_pause(int p) { static wchar_t oldtitle[512]; - wchar_t title[512], paused_msg[64]; + wchar_t title[1024], paused_msg[512]; if (p == dopause) { #ifdef Q_OS_WINDOWS diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index fd91c3da5..128631282 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -94,7 +94,7 @@ int ui_msgbox_header(int flags, void *header, void* message) { msgBox.exec(); } else { // else scope it to main_window - main_window->showMessage(hdr, msg); + main_window->showMessage(flags, hdr, msg); } return 0; } diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index 675abff26..b6db9e051 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -86,6 +86,7 @@ static SCSI_CARD scsi_cards[] = { { &scsi_ls2000_device, }, { &scsi_lcs6821n_device, }, { &scsi_rt1000b_device, }, + { &scsi_rt1000mc_device, }, { &scsi_t128_device, }, { &scsi_t130b_device, }, #ifdef WALTJE diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index ce43a9cf2..387d650f1 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -156,6 +156,7 @@ typedef struct { double period; int ncr_busy; + uint8_t pos_regs[8]; } ncr5380_t; #define STATE_IDLE 0 @@ -1435,6 +1436,64 @@ t128_write(uint32_t addr, uint8_t val, void *priv) } } +static uint8_t +rt1000b_mc_read(int port, void *priv) +{ + ncr5380_t *ncr_dev = (ncr5380_t *)priv; + + return(ncr_dev->pos_regs[port & 7]); +} + + +static void +rt1000b_mc_write(int port, uint8_t val, void *priv) +{ + ncr5380_t *ncr_dev = (ncr5380_t *)priv; + + /* MCA does not write registers below 0x0100. */ + if (port < 0x0102) return; + + mem_mapping_disable(&ncr_dev->bios_rom.mapping); + mem_mapping_disable(&ncr_dev->mapping); + + /* Save the MCA register value. */ + ncr_dev->pos_regs[port & 7] = val; + + if (ncr_dev->pos_regs[2] & 1) { + switch (ncr_dev->pos_regs[2] & 0xe0) { + case 0: + ncr_dev->rom_addr = 0xd4000; + break; + case 0x20: + ncr_dev->rom_addr = 0xd0000; + break; + case 0x40: + ncr_dev->rom_addr = 0xcc000; + break; + case 0x60: + ncr_dev->rom_addr = 0xc8000; + break; + case 0xc0: + ncr_dev->rom_addr = 0xdc000; + break; + case 0xe0: + ncr_dev->rom_addr = 0xd8000; + break; + } + + mem_mapping_set_addr(&ncr_dev->bios_rom.mapping, ncr_dev->rom_addr, 0x4000); + mem_mapping_set_addr(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000); + } +} + +static uint8_t +rt1000b_mc_feedb(void *priv) +{ + ncr5380_t *ncr_dev = (ncr5380_t *)priv; + + return ncr_dev->pos_regs[2] & 1; +} + static void * ncr_init(const device_t *info) { @@ -1462,10 +1521,14 @@ ncr_init(const device_t *info) ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); break; - case 1: /* Rancho RT1000B */ + case 1: /* Rancho RT1000B/MC */ ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); ncr_dev->irq = device_get_config_int("irq"); ncr_dev->bios_ver = device_get_config_int("bios_ver"); + if (info->flags & DEVICE_MCA) { + ncr_dev->rom_addr = 0xd8000; + ncr_dev->bios_ver = 1; + } if (ncr_dev->bios_ver == 1) fn = RT1000B_820R_ROM; @@ -1475,10 +1538,20 @@ ncr_init(const device_t *info) rom_init(&ncr_dev->bios_rom, fn, ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, - memio_read, NULL, NULL, - memio_write, NULL, NULL, - ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); + if (info->flags & DEVICE_MCA) { + mem_mapping_add(&ncr_dev->mapping, 0, 0, + memio_read, NULL, NULL, + memio_write, NULL, NULL, + ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); + ncr_dev->pos_regs[0] = 0x8d; + ncr_dev->pos_regs[1] = 0x70; + mca_add(rt1000b_mc_read, rt1000b_mc_write, rt1000b_mc_feedb, NULL, ncr_dev); + } else { + mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, + memio_read, NULL, NULL, + memio_write, NULL, NULL, + ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); + } break; case 2: /* Trantor T130B */ @@ -1580,6 +1653,12 @@ rt1000b_available(void) return(rom_present(RT1000B_820R_ROM) && rom_present(RT1000B_810R_ROM)); } +static int +rt1000b_820_available(void) +{ + return(rom_present(RT1000B_820R_ROM)); +} + static int t130b_available(void) { @@ -1611,6 +1690,8 @@ static const device_config_t ncr5380_mmio_config[] = { .selection = { { .description = "C800H", .value = 0xc8000 }, { .description = "CC00H", .value = 0xcc000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D400H", .value = 0xd4000 }, { .description = "D800H", .value = 0xd8000 }, { .description = "DC00H", .value = 0xdc000 }, { .description = "" } @@ -1646,6 +1727,8 @@ static const device_config_t rancho_config[] = { .selection = { { .description = "C800H", .value = 0xc8000 }, { .description = "CC00H", .value = 0xcc000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D400H", .value = 0xd4000 }, { .description = "D800H", .value = 0xd8000 }, { .description = "DC00H", .value = 0xdc000 }, { .description = "" } @@ -1683,6 +1766,25 @@ static const device_config_t rancho_config[] = { { .name = "", .description = "", .type = CONFIG_END } }; +static const device_config_t rancho_mc_config[] = { + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 5, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 7", .value = 7 }, + { .description = "" } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + static const device_config_t t130b_config[] = { { .name = "bios_addr", @@ -1747,6 +1849,8 @@ static const device_config_t t128_config[] = { .selection = { { .description = "C800H", .value = 0xc8000 }, { .description = "CC00H", .value = 0xcc000 }, + { .description = "D000H", .value = 0xd0000 }, + { .description = "D400H", .value = 0xd4000 }, { .description = "D800H", .value = 0xd8000 }, { .description = "DC00H", .value = 0xdc000 }, { .description = "" } @@ -1806,6 +1910,20 @@ const device_t scsi_rt1000b_device = { .config = rancho_config }; +const device_t scsi_rt1000mc_device = { + .name = "Rancho RT1000B-MC", + .internal_name = "rt1000mc", + .flags = DEVICE_MCA, + .local = 1, + .init = ncr_init, + .close = ncr_close, + .reset = NULL, + { .available = rt1000b_820_available }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = rancho_mc_config +}; + const device_t scsi_t130b_device = { .name = "Trantor T130B", .internal_name = "t130b", diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 4731132f1..7f1c7d770 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -2555,18 +2555,12 @@ rect_fill: if (!cpu_input) { dev->accel.cx = dev->accel.cur_x; dev->accel.cy = dev->accel.cur_y; + dev->accel.oldcy = dev->accel.cy; - dev->accel.sy = dev->accel.maj_axis_pcnt; + dev->accel.xdir = (dev->accel.cmd & 0x20) ? 1 : -1; + dev->accel.ydir = (dev->accel.cmd & 0x80) ? 1 : -1; - if (dev->accel.cx < dev->accel.clip_left) - dev->accel.cx = dev->accel.clip_left; - else if (dev->accel.cx > clip_r) - dev->accel.cx = dev->accel.clip_left; - - dev->accel.sx = dev->accel.sy; - dev->accel.dx = dev->accel.destx_distp; - dev->accel.dy = dev->accel.desty_axstp; - dev->accel.err = dev->accel.err_term; + dev->accel.sy = 0; if (ibm8514_cpu_src(dev)) { dev->data_available = 0; @@ -2579,237 +2573,70 @@ rect_fill: } } - if (dev->accel.cmd & 8) { /*Vector Line*/ - while (count-- && (dev->accel.sy >= 0)) { - if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && - dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { - if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { - mix_dat = mix_mask; /* Mix data = forced to foreground register. */ - } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { - /* Mix data = current video memory value. */ - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, mix_dat); - mix_dat = ((mix_dat & rd_mask) == rd_mask); - mix_dat = mix_dat ? mix_mask : 0; - } + while (count-- && (dev->accel.sy >= 0)) { + if (((dev->accel.cx) >= dev->accel.clip_left && (dev->accel.cx <= clip_r) && + (dev->accel.cy) >= dev->accel.clip_top && (dev->accel.cy) <= clip_b)) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: src_dat = bkgd_color; break; + case 1: src_dat = frgd_color; break; + case 2: src_dat = cpu_dat & 0xff; break; + case 3: src_dat = 0; break; + } - if (ibm8514_cpu_dest(dev)) { - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, src_dat); - if (pixcntl == 3) - src_dat = ((src_dat & rd_mask) == rd_mask); - } else switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { - case 0: src_dat = bkgd_color; break; - case 1: src_dat = frgd_color; break; - case 2: src_dat = cpu_dat & 0xff; break; - case 3: src_dat = 0; break; - } + READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); - - if ((compare_mode == 0) || - ((compare_mode == 0x10) && (dest_dat >= compare)) || - ((compare_mode == 0x18) && (dest_dat < compare)) || - ((compare_mode == 0x20) && (dest_dat != compare)) || - ((compare_mode == 0x28) && (dest_dat == compare)) || - ((compare_mode == 0x30) && (dest_dat <= compare)) || - ((compare_mode == 0x38) && (dest_dat > compare))) { - old_dest_dat = dest_dat; - MIX(mix_dat & mix_mask, dest_dat, src_dat); - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if ((dev->accel.cmd & 4) && dev->accel.sy) { + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + if ((dev->accel.cmd & 4) && (dev->accel.sy < dev->accel.maj_axis_pcnt)) { + if (!dev->accel.sy) { WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); - } else if (!(dev->accel.cmd & 4)) { + } else if ((dev->accel.cmd & 0x40) && dev->accel.sy && (dev->accel.cy == dev->accel.oldcy + 1)) { + WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 0x40) && dev->accel.sy && (dev->accel.err_term >= 0) && (dev->accel.cy == (dev->accel.oldcy + 1))) { WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); } } } - mix_dat <<= 1; - mix_dat |= 1; - cpu_dat >>= 8; - - if (dev->accel.sy == 0) { - break; - } - - switch (dev->accel.cmd & 0xe0) { - case 0x00: dev->accel.cx++; break; - case 0x20: dev->accel.cx++; dev->accel.cy--; break; - case 0x40: dev->accel.cy--; break; - case 0x60: dev->accel.cx--; dev->accel.cy--; break; - case 0x80: dev->accel.cx--; break; - case 0xa0: dev->accel.cx--; dev->accel.cy++; break; - case 0xc0: dev->accel.cy++; break; - case 0xe0: dev->accel.cx++; dev->accel.cy++; break; - } - - dev->accel.sy--; } - } else { /*Bresenham*/ - if (pixcntl == 1) { - dev->accel.temp_cnt = 8; - while (count-- && (dev->accel.sy >= 0)) { - if (dev->accel.temp_cnt == 0) { - dev->accel.temp_cnt = 8; - mix_dat = old_mix_dat; - } - if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && - dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { - if (ibm8514_cpu_dest(dev)) { - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, src_dat); - } else switch ((mix_dat & 1) ? frgd_mix : bkgd_mix) { - case 0: src_dat = bkgd_color; break; - case 1: src_dat = frgd_color; break; - case 2: src_dat = cpu_dat & 0xff; break; - case 3: src_dat = 0; break; - } - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + mix_dat <<= 1; + mix_dat |= 1; + cpu_dat >>= 8; - if ((compare_mode == 0) || - ((compare_mode == 0x10) && (dest_dat >= compare)) || - ((compare_mode == 0x18) && (dest_dat < compare)) || - ((compare_mode == 0x20) && (dest_dat != compare)) || - ((compare_mode == 0x28) && (dest_dat == compare)) || - ((compare_mode == 0x30) && (dest_dat <= compare)) || - ((compare_mode == 0x38) && (dest_dat > compare))) { - old_dest_dat = dest_dat; - MIX(mix_dat & 1, dest_dat, src_dat); - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if ((dev->accel.cmd & 4) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); - } else if (!(dev->accel.cmd & 4)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); - } - } - } - dev->accel.temp_cnt--; - mix_dat >>= 1; - cpu_dat >>= 8; + if (dev->accel.sy == dev->accel.maj_axis_pcnt) { + return; + } - if (dev->accel.sy == 0) { - break; - } - - if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { - dev->accel.err_term += dev->accel.destx_distp; - /*Step minor axis*/ - switch (dev->accel.cmd & 0xe0) { - case 0x00: dev->accel.cy--; break; - case 0x20: dev->accel.cy--; break; - case 0x40: dev->accel.cx--; break; - case 0x60: dev->accel.cx++; break; - case 0x80: dev->accel.cy++; break; - case 0xa0: dev->accel.cy++; break; - case 0xc0: dev->accel.cx--; break; - case 0xe0: dev->accel.cx++; break; - } - } else - dev->accel.err_term += dev->accel.desty_axstp; - - /*Step major axis*/ - switch (dev->accel.cmd & 0xe0) { - case 0x00: dev->accel.cx--; break; - case 0x20: dev->accel.cx++; break; - case 0x40: dev->accel.cy--; break; - case 0x60: dev->accel.cy--; break; - case 0x80: dev->accel.cx--; break; - case 0xa0: dev->accel.cx++; break; - case 0xc0: dev->accel.cy++; break; - case 0xe0: dev->accel.cy++; break; - } - - dev->accel.sy--; + if (dev->accel.cmd & 0x40) { + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy += dev->accel.ydir; + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + dev->accel.cx += dev->accel.xdir; + } else { + dev->accel.err_term += dev->accel.desty_axstp; } } else { - while (count-- && (dev->accel.sy >= 0)) { - if (dev->accel.cx < dev->accel.clip_left) - dev->accel.cx = dev->accel.clip_left; - else if (dev->accel.cx > clip_r) - dev->accel.cx = dev->accel.clip_left; - - if (((dev->accel.cx) >= dev->accel.clip_left && (dev->accel.cx) <= clip_r && - (dev->accel.cy) >= dev->accel.clip_top && (dev->accel.cy) <= clip_b)) { - if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { - mix_dat = mix_mask; /* Mix data = forced to foreground register. */ - } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { - /* Mix data = current video memory value. */ - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, mix_dat); - mix_dat = ((mix_dat & rd_mask) == rd_mask); - mix_dat = mix_dat ? mix_mask : 0; - } - - if (ibm8514_cpu_dest(dev)) { - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, src_dat); - if (pixcntl == 3) - src_dat = ((src_dat & rd_mask) == rd_mask); - } else switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { - case 0: src_dat = bkgd_color; break; - case 1: src_dat = frgd_color; break; - case 2: src_dat = cpu_dat & 0xff; break; - case 3: src_dat = 0; break; - } - - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); - - if ((compare_mode == 0) || - ((compare_mode == 0x10) && (dest_dat >= compare)) || - ((compare_mode == 0x18) && (dest_dat < compare)) || - ((compare_mode == 0x20) && (dest_dat != compare)) || - ((compare_mode == 0x28) && (dest_dat == compare)) || - ((compare_mode == 0x30) && (dest_dat <= compare)) || - ((compare_mode == 0x38) && (dest_dat > compare))) { - old_dest_dat = dest_dat; - MIX(mix_dat & mix_mask, dest_dat, src_dat); - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if ((dev->accel.cmd & 4) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); - } else if (!(dev->accel.cmd & 4)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); - } - } - } - - mix_dat <<= 1; - mix_dat |= 1; - cpu_dat >>= 8; - - if (dev->accel.sy == 0) { - break; - } - - if (dev->accel.err >= dev->accel.sx) { - dev->accel.err += dev->accel.dx; - /*Step minor axis*/ - switch (dev->accel.cmd & 0xe0) { - case 0x00: dev->accel.cy--; break; - case 0x20: dev->accel.cy--; break; - case 0x40: dev->accel.cx--; break; - case 0x60: dev->accel.cx++; break; - case 0x80: dev->accel.cy++; break; - case 0xa0: dev->accel.cy++; break; - case 0xc0: dev->accel.cx--; break; - case 0xe0: dev->accel.cx++; break; - } - } else - dev->accel.err += dev->accel.dy; - - /*Step major axis*/ - switch (dev->accel.cmd & 0xe0) { - case 0x00: dev->accel.cx--; break; - case 0x20: dev->accel.cx++; break; - case 0x40: dev->accel.cy--; break; - case 0x60: dev->accel.cy--; break; - case 0x80: dev->accel.cx--; break; - case 0xa0: dev->accel.cx++; break; - case 0xc0: dev->accel.cy++; break; - case 0xe0: dev->accel.cy++; break; - } - - dev->accel.sy--; + dev->accel.cx += dev->accel.xdir; + if (dev->accel.err_term >= 0) { + dev->accel.err_term += dev->accel.destx_distp; + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy += dev->accel.ydir; + } else { + dev->accel.err_term += dev->accel.desty_axstp; } } + + dev->accel.sy++; } - dev->accel.cur_x = dev->accel.cx; - dev->accel.cur_y = dev->accel.cy; break; case 6: /*BitBlt*/ diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index e956cb12e..d810536b3 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -2363,7 +2363,12 @@ pgc_cga_text(pgc_t *dev, int w) val = cols[(fontdatm[chr + dev->fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ 0x0f; else val = cols[(fontdatm[chr + dev->fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0]; - buffer32->line[dev->displine][(x * cw) + c] = val; + if (cw == 8) /* 80x25 CGA text screen. */ + buffer32->line[dev->displine][(x * cw) + c] = val; + else { /* 40x25 CGA text screen. */ + buffer32->line[dev->displine][(x * cw) + (c * 2)] = val; + buffer32->line[dev->displine][(x * cw) + (c * 2) + 1] = val; + } } ma++; diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 4755a0b8e..60e6f3d67 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -2704,7 +2704,7 @@ static void xga->on = 0; xga->hwcursor.cur_xsize = 64; xga->hwcursor.cur_ysize = 64; - xga->bios_rom.sz = 0x2000; + xga->bios_rom.sz = 0x8000; f = rom_fopen(xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, "rb"); (void)fseek(f, 0L, SEEK_END); @@ -2729,7 +2729,7 @@ static void xga->instance = 0; xga->rom_addr = 0; mem_mapping_add(&xga->bios_rom.mapping, - 0xdc000, xga->bios_rom.sz, + 0xd8000, xga->bios_rom.sz, rom_read, rom_readw, rom_readl, NULL, NULL, NULL, xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, &xga->bios_rom); diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 9c52afaaa..f44df8dde 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -71,7 +71,7 @@ ifeq ($(DEV_BUILD), y) OPEN_AT := y endif ifndef PAS16 - PAS16 := n + PAS16 := y endif ifndef SIO_DETECT SIO_DETECT := y diff --git a/src/win/languages/cs-CZ.rc b/src/win/languages/cs-CZ.rc index 73d4effe1..a28b99a84 100644 --- a/src/win/languages/cs-CZ.rc +++ b/src/win/languages/cs-CZ.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Grafika:" #define STR_VOODOO "Použít grafický akcelerátor Voodoo" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Myš:" #define STR_JOYSTICK "Joystick:" diff --git a/src/win/languages/de-DE.rc b/src/win/languages/de-DE.rc index 72ad32e54..27644e4a7 100644 --- a/src/win/languages/de-DE.rc +++ b/src/win/languages/de-DE.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Videokarte:" #define STR_VOODOO "Voodoo-Grafik" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Maus:" #define STR_JOYSTICK "Joystick:" diff --git a/src/win/languages/dialogs.rc b/src/win/languages/dialogs.rc index 9d01e4cdf..45a767ea3 100644 --- a/src/win/languages/dialogs.rc +++ b/src/win/languages/dialogs.rc @@ -269,6 +269,12 @@ BEGIN CONTROL STR_IBM8514, IDC_CHECK_IBM8514, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 7, 46, 199, CFG_CHECKBOX_HEIGHT + + CONTROL STR_XGA, IDC_CHECK_XGA, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + 7, 65, 199, CFG_CHECKBOX_HEIGHT + PUSHBUTTON STR_CONFIGURE, IDC_BUTTON_XGA, + CFG_COMBO_BTN_LEFT, 64, CFG_BTN_WIDTH, CFG_BTN_HEIGHT END DLG_CFG_INPUT DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT @@ -727,7 +733,7 @@ BEGIN LTEXT STR_CD_SPEED, IDT_CD_SPEED, CFG_HMARGIN, 207, 34, CFG_PANE_LTEXT_HEIGHT COMBOBOX IDC_COMBO_CD_SPEED, - 43, 205, 328, 12, + 33, 205, 328, 12, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP END diff --git a/src/win/languages/en-GB.rc b/src/win/languages/en-GB.rc index 82cb16cc5..fbbb982cf 100644 --- a/src/win/languages/en-GB.rc +++ b/src/win/languages/en-GB.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Video:" #define STR_VOODOO "Voodoo Graphics" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Mouse:" #define STR_JOYSTICK "Joystick:" diff --git a/src/win/languages/en-US.rc b/src/win/languages/en-US.rc index ac3682818..5a5839686 100644 --- a/src/win/languages/en-US.rc +++ b/src/win/languages/en-US.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Video:" #define STR_VOODOO "Voodoo Graphics" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Mouse:" #define STR_JOYSTICK "Joystick:" diff --git a/src/win/languages/es-ES.rc b/src/win/languages/es-ES.rc index b5161aad0..b7eb61d24 100644 --- a/src/win/languages/es-ES.rc +++ b/src/win/languages/es-ES.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Vídeo:" #define STR_VOODOO "Voodoo Graphics" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Ratón:" #define STR_JOYSTICK "Mando:" diff --git a/src/win/languages/fi-FI.rc b/src/win/languages/fi-FI.rc index 8b394f550..a8dc55b72 100644 --- a/src/win/languages/fi-FI.rc +++ b/src/win/languages/fi-FI.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Näytönohjain:" #define STR_VOODOO "Voodoo-grafiikkasuoritin" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Hiiri:" #define STR_JOYSTICK "Peliohjain:" diff --git a/src/win/languages/fr-FR.rc b/src/win/languages/fr-FR.rc index e63bb831a..11fc3360e 100644 --- a/src/win/languages/fr-FR.rc +++ b/src/win/languages/fr-FR.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Vidéo:" #define STR_VOODOO "Graphique Voodoo" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Souris:" #define STR_JOYSTICK "Manette de commande:" diff --git a/src/win/languages/hr-HR.rc b/src/win/languages/hr-HR.rc index da3954cd1..60e6e28c4 100644 --- a/src/win/languages/hr-HR.rc +++ b/src/win/languages/hr-HR.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Video:" #define STR_VOODOO "Voodoo grafika" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Miš:" #define STR_JOYSTICK "Palica za igru:" diff --git a/src/win/languages/hu-HU.rc b/src/win/languages/hu-HU.rc index 8ac86adff..6b4dae959 100644 --- a/src/win/languages/hu-HU.rc +++ b/src/win/languages/hu-HU.rc @@ -277,6 +277,7 @@ END #define STR_VIDEO "Videokártya:" #define STR_VOODOO "Voodoo-gyorsítókártya" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Egér:" #define STR_JOYSTICK "Játékvezérlő:" diff --git a/src/win/languages/it-IT.rc b/src/win/languages/it-IT.rc index 254491072..20d301f47 100644 --- a/src/win/languages/it-IT.rc +++ b/src/win/languages/it-IT.rc @@ -273,6 +273,7 @@ END #define STR_VIDEO "Video:" #define STR_VOODOO "Grafica Voodoo" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Mouse:" #define STR_JOYSTICK "Joystick:" diff --git a/src/win/languages/ja-JP.rc b/src/win/languages/ja-JP.rc index 01f0d7a24..151e13e65 100644 --- a/src/win/languages/ja-JP.rc +++ b/src/win/languages/ja-JP.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "ビデオカード:" #define STR_VOODOO "Voodooグラフィック" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "マウス:" #define STR_JOYSTICK "ジョイスティック:" diff --git a/src/win/languages/ko-KR.rc b/src/win/languages/ko-KR.rc index c039e8129..831ca74bb 100644 --- a/src/win/languages/ko-KR.rc +++ b/src/win/languages/ko-KR.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "비디오 카드:" #define STR_VOODOO "Voodoo 그래픽" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "마우스:" #define STR_JOYSTICK "조이스틱:" diff --git a/src/win/languages/pl-PL.rc b/src/win/languages/pl-PL.rc index 3c99f963d..211eb3ed8 100644 --- a/src/win/languages/pl-PL.rc +++ b/src/win/languages/pl-PL.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Wideo:" #define STR_VOODOO "Grafika Voodoo" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Mysz:" #define STR_JOYSTICK "Joystick:" diff --git a/src/win/languages/pt-BR.rc b/src/win/languages/pt-BR.rc index ef75f2495..81b2e290a 100644 --- a/src/win/languages/pt-BR.rc +++ b/src/win/languages/pt-BR.rc @@ -275,6 +275,7 @@ END #define STR_VIDEO "Vídeo:" #define STR_VOODOO "3DFX Voodoo" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Mouse:" #define STR_JOYSTICK "Joystick:" diff --git a/src/win/languages/pt-PT.rc b/src/win/languages/pt-PT.rc index b2359b2e6..fafc21df4 100644 --- a/src/win/languages/pt-PT.rc +++ b/src/win/languages/pt-PT.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Vídeo:" #define STR_VOODOO "Gráficos Voodoo" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Rato:" #define STR_JOYSTICK "Joystick:" diff --git a/src/win/languages/ru-RU.rc b/src/win/languages/ru-RU.rc index c3c24575e..15bd1752d 100644 --- a/src/win/languages/ru-RU.rc +++ b/src/win/languages/ru-RU.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Видеокарта:" #define STR_VOODOO "Ускоритель Voodoo" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Мышь:" #define STR_JOYSTICK "Джойстик:" diff --git a/src/win/languages/sl-SI.rc b/src/win/languages/sl-SI.rc index b4fdba000..7d715c5ca 100644 --- a/src/win/languages/sl-SI.rc +++ b/src/win/languages/sl-SI.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Video:" #define STR_VOODOO "Voodoo grafika" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Miška:" #define STR_JOYSTICK "Igralna palica:" diff --git a/src/win/languages/tr-TR.rc b/src/win/languages/tr-TR.rc index 8368380bb..cc3a98406 100644 --- a/src/win/languages/tr-TR.rc +++ b/src/win/languages/tr-TR.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Ekran kartı:" #define STR_VOODOO "Voodoo Grafikleri" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Fare:" #define STR_JOYSTICK "Oyun kolu:" diff --git a/src/win/languages/uk-UA.rc b/src/win/languages/uk-UA.rc index b2a091cbe..dfb86cc8b 100644 --- a/src/win/languages/uk-UA.rc +++ b/src/win/languages/uk-UA.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "Відеокарта:" #define STR_VOODOO "Прискорювач Voodoo" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "Миша:" #define STR_JOYSTICK "Джойстик:" diff --git a/src/win/languages/zh-CN.rc b/src/win/languages/zh-CN.rc index 14497df62..a3c324c6c 100644 --- a/src/win/languages/zh-CN.rc +++ b/src/win/languages/zh-CN.rc @@ -272,6 +272,7 @@ END #define STR_VIDEO "显卡:" #define STR_VOODOO "Voodoo Graphics" #define STR_IBM8514 "IBM 8514/a Graphics" +#define STR_XGA "XGA Graphics" #define STR_MOUSE "鼠标:" #define STR_JOYSTICK "操纵杆:" diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 29cc23198..84ad26754 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -16,6 +16,7 @@ * Copyright 2016-2019 Miran Grca. * Copyright 2018,2019 David Hrdlička. * Copyright 2021 Laci bá' + * Copyright 2021-2022 Jasmine Iwanek. */ #define UNICODE #define BITMAP WINDOWS_BITMAP @@ -63,6 +64,7 @@ #include <86box/midi.h> #include <86box/snd_mpu401.h> #include <86box/video.h> +#include <86box/vid_xga_device.h> #include <86box/plat.h> #include <86box/ui.h> #include <86box/win.h> @@ -85,7 +87,7 @@ static int temp_dynarec; #endif /* Video category */ -static int temp_gfxcard, temp_ibm8514, temp_voodoo; +static int temp_gfxcard, temp_ibm8514, temp_voodoo, temp_xga; /* Input devices category */ static int temp_mouse, temp_joystick; @@ -333,6 +335,7 @@ win_settings_init(void) temp_gfxcard = gfxcard; temp_voodoo = voodoo_enabled; temp_ibm8514 = ibm8514_enabled; + temp_xga = xga_enabled; /* Input devices category */ temp_mouse = mouse_type; @@ -458,6 +461,7 @@ win_settings_changed(void) i = i || (gfxcard != temp_gfxcard); i = i || (voodoo_enabled != temp_voodoo); i = i || (ibm8514_enabled != temp_ibm8514); + i = i || (xga_enabled != temp_xga); /* Input devices category */ i = i || (mouse_type != temp_mouse); @@ -549,6 +553,7 @@ win_settings_save(void) gfxcard = temp_gfxcard; voodoo_enabled = temp_voodoo; ibm8514_enabled = temp_ibm8514; + xga_enabled = temp_xga; /* Input devices category */ mouse_type = temp_mouse; @@ -1116,6 +1121,11 @@ win_settings_video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) settings_enable_window(hdlg, IDC_CHECK_IBM8514, machine_has_bus(temp_machine, MACHINE_BUS_ISA16) || machine_has_bus(temp_machine, MACHINE_BUS_MCA)); settings_set_check(hdlg, IDC_CHECK_IBM8514, temp_ibm8514); + + settings_enable_window(hdlg, IDC_CHECK_XGA, machine_has_bus(temp_machine, MACHINE_BUS_ISA16) || machine_has_bus(temp_machine, MACHINE_BUS_MCA)); + settings_set_check(hdlg, IDC_CHECK_XGA, temp_xga); + settings_enable_window(hdlg, IDC_BUTTON_XGA, (machine_has_bus(temp_machine, MACHINE_BUS_ISA16) || machine_has_bus(temp_machine, MACHINE_BUS_MCA)) && temp_xga); + return TRUE; case WM_COMMAND: @@ -1134,10 +1144,23 @@ win_settings_video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) temp_ibm8514 = settings_get_check(hdlg, IDC_CHECK_IBM8514); break; + case IDC_CHECK_XGA: + temp_xga = settings_get_check(hdlg, IDC_CHECK_XGA); + settings_enable_window(hdlg, IDC_BUTTON_XGA, temp_xga); + break; + case IDC_BUTTON_VOODOO: temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&voodoo_device); break; + case IDC_BUTTON_XGA: + if (machine_has_bus(temp_machine, MACHINE_BUS_MCA) > 0) { + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&xga_device); + } else { + temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&xga_isa_device); + } + break; + case IDC_CONFIGURE_VID: temp_gfxcard = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO)]; temp_deviceconfig |= deviceconfig_open(hdlg, (void *)video_card_getdevice(temp_gfxcard)); @@ -1149,6 +1172,7 @@ win_settings_video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) temp_gfxcard = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_VIDEO)]; temp_voodoo = settings_get_check(hdlg, IDC_CHECK_VOODOO); temp_ibm8514 = settings_get_check(hdlg, IDC_CHECK_IBM8514); + temp_xga = settings_get_check(hdlg, IDC_CHECK_XGA); default: return FALSE;