diff --git a/README.md b/README.md index cfe06860f..b2b744686 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ to retro computing and, of course, 86Box. We look forward to hearing from you! Getting started --------------- -See [this](https://86box.github.io/gettingstarted) page on our website for a quick guide that should help you get started with the emulator. +See [our documentation](https://86box.readthedocs.io/en/latest/index.html) for an overview of the emulator's features and user interface. Building -------- diff --git a/src/chipset/umc491.c b/src/chipset/umc491.c new file mode 100644 index 000000000..4de917784 --- /dev/null +++ b/src/chipset/umc491.c @@ -0,0 +1,179 @@ +/* + * 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. + * + * Implementation of the UMC 491/493 chipset. + * + * + * + * Authors: Tiseno100 + * + * Copyright 2020 Tiseno100 + * + */ + +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/port_92.h> +#include <86box/chipset.h> + +#ifdef ENABLE_UMC491_LOG +int ali1429_do_log = ENABLE_UMC491_LOG; +static void +umc491_log(const char *fmt, ...) +{ + va_list ap; + + if (umc491_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define umc491_log(fmt, ...) +#endif + +typedef struct +{ + uint8_t index, + regs[256]; +} umc491_t; + +static void umc491_shadow_recalc(umc491_t *dev) +{ + +shadowbios = (dev->regs[0xcc] & 0x40); +shadowbios_write = (dev->regs[0xcc] & 0x80); + +mem_set_mem_state_both(0xc0000, 0x4000, ((dev->regs[0xcd] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xcd] & 0x80) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); +mem_set_mem_state_both(0xc4000, 0x4000, ((dev->regs[0xcd] & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xcd] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); +mem_set_mem_state_both(0xc8000, 0x4000, ((dev->regs[0xcd] & 0x04) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xcd] & 0x08) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); +mem_set_mem_state_both(0xcc000, 0x4000, ((dev->regs[0xcd] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xcd] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + +mem_set_mem_state_both(0xd0000, 0x4000, ((dev->regs[0xce] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xce] & 0x80) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); +mem_set_mem_state_both(0xd4000, 0x4000, ((dev->regs[0xce] & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xce] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); +mem_set_mem_state_both(0xd8000, 0x4000, ((dev->regs[0xce] & 0x04) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xce] & 0x08) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); +mem_set_mem_state_both(0xdc000, 0x4000, ((dev->regs[0xce] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xce] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + +/* +Our machine has the E segment into parts although most AMI machines treat it as one. +Probably a flaw by the BIOS as only one register gets enabled for it anyways. +*/ +mem_set_mem_state_both(0xe0000, 0x10000, ((dev->regs[0xcc] & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xcc] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + +mem_set_mem_state_both(0xf0000, 0x10000, ((dev->regs[0xcc] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0xcc] & 0x80) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)); + +flushmmucache(); +} + +static void +umc491_write(uint16_t addr, uint8_t val, void *priv) +{ + umc491_t *dev = (umc491_t *) priv; + + switch (addr) { + case 0x8022: + dev->index = val; + break; + case 0x8024: + umc491_log("UMC 491: dev->regs[%02x] = %02x\n", dev->index, val); + dev->regs[dev->index] = val; + + switch(dev->index) + { + case 0xcc: + case 0xcd: + case 0xce: + umc491_shadow_recalc(dev); + break; + + case 0xd0: + cpu_update_waitstates(); + break; + + case 0xd1: + cpu_cache_ext_enabled = (val & 0x01); + break; + } + break; + } +} + + +static uint8_t +umc491_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + umc491_t *dev = (umc491_t *) priv; + + switch (addr) { + case 0x8024: + ret = dev->regs[dev->index]; + break; + } + + return ret; +} + + +static void +umc491_close(void *priv) +{ + umc491_t *dev = (umc491_t *) priv; + + free(dev); +} + + +static void * +umc491_init(const device_t *info) +{ + umc491_t *dev = (umc491_t *) malloc(sizeof(umc491_t)); + memset(dev, 0, sizeof(umc491_t)); + + device_add(&port_92_device); + +/* + +UMC 491/493 Ports + +8022h Index Port +8024h Data Port + +*/ + io_sethandler(0x8022, 0x0001, umc491_read, NULL, NULL, umc491_write, NULL, NULL, dev); + io_sethandler(0x8024, 0x0001, umc491_read, NULL, NULL, umc491_write, NULL, NULL, dev); + + dev->regs[0xcc] = 0x00; + dev->regs[0xcd] = 0x00; + dev->regs[0xce] = 0x00; + umc491_shadow_recalc(dev); + + return dev; +} + + +const device_t umc491_device = { + "UMC 491/493", + 0, + 0, + umc491_init, umc491_close, NULL, + NULL, NULL, NULL, + NULL +}; diff --git a/src/floppy/fdd_imd.c b/src/floppy/fdd_imd.c index 608805b3d..a52a35c38 100644 --- a/src/floppy/fdd_imd.c +++ b/src/floppy/fdd_imd.c @@ -328,12 +328,15 @@ imd_seek(int drive, int track) d86f_destroy_linked_lists(drive, 0); d86f_destroy_linked_lists(drive, 1); - if (track > dev->track_count) { - d86f_zero_track(drive); + d86f_zero_track(drive); + + if (track > dev->track_count) return; - } for (side = 0; side < dev->sides; side++) { + if (!dev->tracks[track][side].is_present) + continue; + track_rate = dev->current_side_flags[side] & 7; if (!track_rate && (dev->current_side_flags[side] & 0x20)) track_rate = 4; @@ -414,11 +417,11 @@ imd_seek(int drive, int track) data = dev->track_buffer[side] + track_buf_pos[side]; type = dev->buffer[dev->tracks[track][side].sector_data_offs[ordered_pos]]; - type = (type >> 1) & 7; + type = ((type - 1) >> 1) & 7; flags = 0x00; - if ((type == 2) || (type == 4)) + if (type & 0x01) flags |= SECTOR_DELETED_DATA; - if ((type == 3) || (type == 4)) + if (type & 0x02) flags |= SECTOR_CRC_ERROR; if (((flags & 0x02) || (id[3] > dev->tracks[track][side].max_sector_size)) && !fdd_get_turbo(drive)) @@ -717,6 +720,7 @@ imd_load(int drive, wchar_t *fn) track_spt = buffer2[3]; sector_size = buffer2[4]; + pclog("%02X %02X %02X %02X\n", buffer2[1], buffer2[2], buffer2[3], buffer2[4]); if ((track_spt == 15) && (sector_size == 2)) dev->tracks[track][side].side_flags |= 0x20; if ((track_spt == 16) && (sector_size == 2)) @@ -750,7 +754,12 @@ imd_load(int drive, wchar_t *fn) last_offset += track_spt; } - if (sector_size == 0xFF) { + if (track_spt == 0x00) { + dev->tracks[track][side].n_map_offs = last_offset; + buffer2 = buffer + last_offset; + last_offset += track_spt; + dev->tracks[track][side].is_present = 0; + } else if (sector_size == 0xFF) { dev->tracks[track][side].n_map_offs = last_offset; buffer2 = buffer + last_offset; last_offset += track_spt; @@ -762,17 +771,29 @@ imd_load(int drive, wchar_t *fn) data_size = 128 << data_size; dev->tracks[track][side].sector_data_offs[i] = last_offset; dev->tracks[track][side].sector_data_size[i] = 1; + if (dev->buffer[dev->tracks[track][side].sector_data_offs[i]] > 0x08) { + /* Invalid sector data type, possibly a malformed HxC IMG image (it outputs data errored + sectors with a variable amount of bytes, against the specification). */ + imd_log("IMD: Invalid sector data type %02X\n", dev->buffer[dev->tracks[track][side].sector_data_offs[i]]); + fclose(dev->f); + free(dev); + imd[drive] = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } if (buffer[dev->tracks[track][side].sector_data_offs[i]] != 0) dev->tracks[track][side].sector_data_size[i] += (buffer[dev->tracks[track][side].sector_data_offs[i]] & 1) ? data_size : 1; last_offset += dev->tracks[track][side].sector_data_size[i]; if (!(buffer[dev->tracks[track][side].sector_data_offs[i]] & 1)) fwriteprot[drive] = writeprot[drive] = 1; type = dev->buffer[dev->tracks[track][side].sector_data_offs[i]]; - type = (type >> 1) & 7; - if ((type == 3) || (type == 4) || (data_size > (128 << dev->tracks[track][side].max_sector_size))) - track_total += (pre_sector + 3); - else - track_total += (pre_sector + data_size + 2); + if (type != 0x00) { + type = ((type - 1) >> 1) & 7; + if (data_size > (128 << dev->tracks[track][side].max_sector_size)) + track_total += (pre_sector + 3); + else + track_total += (pre_sector + data_size + 2); + } } } else { dev->tracks[track][side].data_offs = last_offset; @@ -782,19 +803,32 @@ imd_load(int drive, wchar_t *fn) data_size = 128 << data_size; dev->tracks[track][side].sector_data_offs[i] = last_offset; dev->tracks[track][side].sector_data_size[i] = 1; + if (dev->buffer[dev->tracks[track][side].sector_data_offs[i]] > 0x08) { + /* Invalid sector data type, possibly a malformed HxC IMG image (it outputs data errored + sectors with a variable amount of bytes, against the specification). */ + imd_log("IMD: Invalid sector data type %02X\n", dev->buffer[dev->tracks[track][side].sector_data_offs[i]]); + fclose(dev->f); + free(dev); + imd[drive] = NULL; + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } if (buffer[dev->tracks[track][side].sector_data_offs[i]] != 0) dev->tracks[track][side].sector_data_size[i] += (buffer[dev->tracks[track][side].sector_data_offs[i]] & 1) ? data_size : 1; last_offset += dev->tracks[track][side].sector_data_size[i]; if (!(buffer[dev->tracks[track][side].sector_data_offs[i]] & 1)) fwriteprot[drive] = writeprot[drive] = 1; type = dev->buffer[dev->tracks[track][side].sector_data_offs[i]]; - type = (type >> 1) & 7; - if ((type == 3) || (type == 4) || (sector_size > dev->tracks[track][side].max_sector_size)) - track_total += (pre_sector + 3); - else - track_total += (pre_sector + data_size + 2); + if (type != 0x00) { + type = ((type - 1) >> 1) & 7; + if (data_size > (128 << dev->tracks[track][side].max_sector_size)) + track_total += (pre_sector + 3); + else + track_total += (pre_sector + data_size + 2); + } } } + buffer2 = buffer + last_offset; /* Leaving even GAP4: 80 : 40 */ @@ -810,7 +844,7 @@ imd_load(int drive, wchar_t *fn) else converted_rate = dev->tracks[track][side].side_flags & 0x03; - if (gap3_sizes[converted_rate][sector_size][track_spt] == 0x00) { + if ((track_spt != 0x00) && (gap3_sizes[converted_rate][sector_size][track_spt] == 0x00)) { size_diff = raw_tsize - track_total; gap_sum = minimum_gap3 + minimum_gap4; if (size_diff < gap_sum) { @@ -831,7 +865,7 @@ imd_load(int drive, wchar_t *fn) } dev->tracks[track][side].gap3_len = (size_diff - minimum_gap4) / track_spt; - } else if (gap3_sizes[converted_rate][sector_size][track_spt] != 0x00) + } else if ((track_spt == 0x00) || (gap3_sizes[converted_rate][sector_size][track_spt] != 0x00)) dev->tracks[track][side].gap3_len = gap3_sizes[converted_rate][sector_size][track_spt]; /* imd_log("GAP3 length for (%02i)(%01i): %i bytes\n", track, side, dev->tracks[track][side].gap3_len); */ @@ -839,7 +873,8 @@ imd_load(int drive, wchar_t *fn) if (track > dev->track_count) dev->track_count = track; - if (last_offset >= fsize) break; + if (last_offset >= fsize) + break; } /* If more than 43 tracks, then the tracks are thin (96 tpi). */ diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index cddd86100..2b4fff78d 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -104,6 +104,9 @@ extern const device_t stpc_serial_device; extern const device_t stpc_lpt_device; #endif +/* UMC */ +extern const device_t umc491_device; + /* VIA */ extern const device_t via_vt82c49x_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 76604b298..bae2e0965 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -252,6 +252,7 @@ extern const device_t *at_commodore_sl386sx_get_device(void); extern int machine_at_acc386_init(const machine_t *); extern int machine_at_asus386_init(const machine_t *); extern int machine_at_ecs386_init(const machine_t *); +extern int machine_at_ustechnologies386_init(const machine_t *); extern int machine_at_micronics386_init(const machine_t *); extern int machine_at_rycleopardlx_init(const machine_t *); diff --git a/src/include/86box/win_sdl.h b/src/include/86box/win_sdl.h index c157c6f59..97ee42090 100644 --- a/src/include/86box/win_sdl.h +++ b/src/include/86box/win_sdl.h @@ -58,6 +58,7 @@ extern int sdl_inith_fs(HWND h); extern int sdl_pause(void); extern void sdl_resize(int x, int y); extern void sdl_enable(int enable); +extern void sdl_reinit_texture(); #endif /*WIN_SDL_H*/ diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 474ff3e1d..dbaf729b7 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -103,6 +103,26 @@ machine_at_ecs386_init(const machine_t *model) return ret; } +int +machine_at_ustechnologies386_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/ustechnologies386/3umw003.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&umc491_device); + device_add(&keyboard_at_device); + device_add(&fdc_at_device); + + return ret; +} + int machine_at_rycleopardlx_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 7b7ab6a9a..6c3d5dfc0 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -187,6 +187,7 @@ const machine_t machines[] = { { "[ISA] Compaq Portable III (386)", "portableiii386", MACHINE_TYPE_386DX, {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 1, 14, 1, 127, machine_at_portableiii386_init, at_cpqiii_get_device }, { "[ISA] Micronics 386 clone", "micronics386", MACHINE_TYPE_386DX, {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, { "[C&T 386] ECS 386/32", "ecs386", MACHINE_TYPE_386DX, {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 1, 16, 1, 127, machine_at_ecs386_init, NULL }, + { "[UMC 491] US Technologies 386", "ustechnologies386", MACHINE_TYPE_386DX, {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 1, 16, 1, 127, machine_at_ustechnologies386_init, NULL }, /* 386DX machines which utilize the VLB bus */ { "[OPTi 495] Award 386DX clone", "award386dx", MACHINE_TYPE_386DX, {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index ea362b2b8..84cd3750e 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -639,7 +639,7 @@ CPUOBJ := cpu.o cpu_table.o \ CHIPSETOBJ := acc2168.o cs8230.o ali1429.o headland.o i82335.o cs4031.o \ intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ neat.o opti495.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \ - sis_85c310.o sis_85c471.o sis_85c496.o opti283.o opti291.o \ + sis_85c310.o sis_85c471.o sis_85c496.o opti283.o opti291.o umc491.o \ via_apollo.o via_vpx.o via_vt82c586b.o via_vt82c596b.o wd76c10.o vl82c480.o \ amd640.o diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c index 11bb948b2..4be55fe34 100644 --- a/src/win/win_sdl.c +++ b/src/win/win_sdl.c @@ -181,6 +181,8 @@ sdl_stretch(int *w, int *h, int *x, int *y) *y = (int) dy; break; } + + sdl_reinit_texture(); } @@ -489,6 +491,18 @@ sdl_inith_fs(HWND h) } +void +sdl_reinit_texture() +{ + if (sdl_render == NULL) + return; + + SDL_DestroyTexture(sdl_tex); + sdl_tex = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, 2048, 2048); +} + + int sdl_pause(void) { @@ -514,6 +528,8 @@ sdl_resize(int x, int y) cur_w = x; cur_h = y; + + sdl_reinit_texture(); }