diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index d1257d94c..21e4a89e2 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -483,6 +483,7 @@ extern int machine_at_adi386sx_init(const machine_t *); extern int machine_at_cmdsl386sx16_init(const machine_t *); extern int machine_at_cmdsl386sx25_init(const machine_t *); extern int machine_at_dataexpert386sx_init(const machine_t *); +extern int machine_at_if386sx_init(const machine_t *); extern int machine_at_spc6033p_init(const machine_t *); extern int machine_at_wd76c10_init(const machine_t *); extern int machine_at_arb1374_init(const machine_t *); diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 2985559e1..6cf9c8d59 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -456,6 +456,9 @@ extern const device_t millennium_ii_device; extern const device_t productiva_g100_device; #endif /* USE_G100 */ +/* JEGA */ +extern const device_t if386jega_device; + /* Oak OTI-0x7 */ extern const device_t oti037c_device; extern const device_t oti067_device; diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index fd9cc3bcd..2f35427be 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -641,6 +641,31 @@ machine_at_cmdsl386sx16_init(const machine_t *model) return ret; } +int +machine_at_if386sx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/if386sx/OKI_IF386SX_odd.bin", + "roms/machines/if386sx/OKI_IF386SX_even.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&keyboard_at_device); + + device_add(&neat_device); + + if (gfxcard[0] == VID_INTERNAL) + device_add(&if386jega_device); + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + static void machine_at_scamp_common_init(const machine_t *model, int is_ps2) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index bae9de29f..ce95b5fc8 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -4746,6 +4746,44 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { .name = "[NEAT] OKI if386AX30L", + .internal_name = "if386sx", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_NEAT, + .init = machine_at_if386sx_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_VIDEO, + .ram = { + .min = 1024, + .max = 4096, + .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 + }, /* Has IBM AT KBC firmware. */ { .name = "[OPTi 291] DTK PPM-3333P", diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 438d5c98d..16a3552ad 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -47,9 +47,9 @@ void ega_doblit(int wx, int wy, ega_t *ega); static video_timings_t timing_ega = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; static uint8_t ega_rotate[8][256]; -static int active = 0; -static uint32_t pallook16[256]; -static uint32_t pallook64[256]; +static int active = 0; +uint32_t pallook16[256]; +uint32_t pallook64[256]; static int ega_type = EGA_TYPE_IBM; static int old_overscan_color = 0; diff --git a/src/video/vid_jega.c b/src/video/vid_jega.c index 145579cf5..edf7358a6 100644 --- a/src/video/vid_jega.c +++ b/src/video/vid_jega.c @@ -60,6 +60,7 @@ #define RINVALID_INDEX 0x30 #define JEGA_PATH_BIOS "roms/video/jega/JEGABIOS.BIN" +#define IF386_PATH_VBIOS "roms/video/jega/OKI_IF386SX_VBIOS.bin" #define JEGA_PATH_FONTDBCS "roms/video/jega/JPNZN16X.FNT" #define SBCS19_FILESIZE (256 * 19 * 2) /* 8 x 19 x 256 chr x 2 pages */ #define DBCS16_CHARS 0x2c10 @@ -137,7 +138,8 @@ typedef struct { uint16_t end; } fontx_tbl; -static uint32_t pallook64[256]; +extern uint32_t pallook16[256]; +extern uint32_t pallook64[256]; static bool is_SJIS_1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); } static bool is_SJIS_2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); } @@ -615,8 +617,27 @@ LoadFontxFile(const char *fn, void *priv) return 0; } +static void +jega_commoninit(void *priv) +{ + jega_t *jega = (jega_t *) priv; + for (int c = 0; c < 256; c++) { + pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); + } + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); + jega->pallook = pallook64; + ega_init(&jega->ega, 9, 0); + ega_set_type(&jega->ega, EGA_SUPEREGA); + jega->ega.priv_parent = jega; + mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, &jega->ega); + /* I/O 3DD and 3DE are used by Oki if386 */ + io_sethandler(0x03b0, 0x002c, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); + jega->regs[RMOD1] = 0x48; +} + static void * -jega_init(const device_t *info) +jega_standalone_init(const device_t *info) { jega_t *jega = calloc(1, sizeof(jega_t)); @@ -624,21 +645,7 @@ jega_init(const device_t *info) memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE); LoadFontxFile(JEGA_PATH_FONTDBCS, jega); - for (int c = 0; c < 256; c++) { - pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); - pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); - } - - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega); - jega->pallook = pallook64; - ega_init(&jega->ega, 9, 0); - ega_set_type(&jega->ega, EGA_SUPEREGA); - jega->ega.priv_parent = jega; - mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, &jega->ega); - - io_sethandler(0x03b0, 0x0030, jega_in, NULL, NULL, jega_out, NULL, NULL, jega); - - jega->regs[RMOD1] = 0x48; + jega_commoninit(jega); return jega; } @@ -665,10 +672,10 @@ jega_close(void *priv) fprintf(f, "Regs %02X: %4X\n", i, jega->regs[i]); for (int i = 0; i < 32; i++) fprintf(f, "Attr %02X: %4X\n", i, jega->attrregs[i]); - for (int i = 0; i < 16; i++) - fprintf(f, "JEGAPal %02X: %4X\n", i, jega->egapal[i]); - for (int i = 0; i < 16; i++) - fprintf(f, "EGAPal %02X: %4X\n", i, jega->ega.egapal[i]); + for (int i = 0; i < 16; i++) + fprintf(f, "JEGAPal %02X: %4X\n", i, jega->egapal[i]); + for (int i = 0; i < 16; i++) + fprintf(f, "EGAPal %02X: %4X\n", i, jega->ega.egapal[i]); for (int i = 0; i < 64; i++) fprintf(f, "RealPal %02X: %4X\n", i, jega->pallook[i]); fclose(f); @@ -683,7 +690,7 @@ jega_close(void *priv) fwrite(&ram[0x0], 0x500, 1, f); fclose(f); } - // jega_log("jeclosed %04X:%04X DS %04X\n", cs >> 4, cpu_state.pc, DS); + pclog("jeclosed %04X:%04X DS %04X\n", cs >> 4, cpu_state.pc, DS); #endif if (jega->ega.eeprom) free(jega->ega.eeprom); @@ -706,7 +713,7 @@ jega_speed_changed(void *priv) } static int -jega_available(void) +jega_standalone_available(void) { return (rom_present(JEGA_PATH_BIOS) && rom_present(JEGA_PATH_FONTDBCS)); } @@ -716,10 +723,124 @@ const device_t jega_device = { .internal_name = "jega", .flags = DEVICE_ISA, .local = 0, - .init = jega_init, + .init = jega_standalone_init, .close = jega_close, .reset = NULL, - .available = jega_available, + .available = jega_standalone_available, + .speed_changed = jega_speed_changed, + .force_redraw = NULL, + .config = NULL +}; + +static uint8_t p65idx = 0; +static uint8_t p3de_idx = 0; +static uint8_t p65[6]; +static uint8_t p3de[0x30]; + + +static uint8_t +if386_p6x_read(uint16_t port, void *priv) +{ + uint8_t ret = INVALIDACCESS8; + if (port == 0x63) { + ret = p65idx; + } else if (port == 0x65) { + ret = p65[p65idx]; + } + // pclog("p%x_r: [%04x:%04x] [%02x]%02x\n", port, cs >> 4, cpu_state.pc , p65idx, ret); + return ret; +} + +/* + OKi if386AX/SX Power management and Miscellaneous + I/O 63h: Index 0-5, I/O 65h: Data + Index 2: + Bit 3: Caps Lock enabled + Bit 2: Num Lock enabled + Bit 1: Scrl Lock enabled + Bit 0: Kana Lock enabled + Index 3 + Bit 2: External monitor output enabled + Bit 1: Floppy drive 1 active + Bit 0: Floppy drive 0 active + Index 5 + Bit 8: ? (1=Disabled, 0=Enabled) + Bit 7: Screen Off? (enabled by Ctrl + Alt + [1] and disabled by any key) + Bit 4: Shutdown? (caused by POST rebooting and POWER OFF command in DOS 3.21) + Bit 3: ? +*/ +static void +if386_p6x_write(uint16_t port, uint8_t val, void *priv) +{ + jega_t *jega = (jega_t *) priv; + // pclog("p%x_w: [%04x:%04x] val=%02x\n", port, cs >> 4, cpu_state.pc, val); + if (port == 0x63 && val < 6) + p65idx = val; + if (port == 0x65) { + // pclog("p65_w: [%04x:%04x] idx=%02x, val=%02x\n", cs >> 4, cpu_state.pc, p65idx, val); + p65[p65idx] = val; + if (p65idx == 0x03) { + if (val & 0x04) { /* Color monitor */ + for (int c = 0; c < 256; c++) { + pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); + pallook16[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook16[c] += makecol32(((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55); + if ((c & 0x17) == 6) + pallook16[c] = makecol32(0xaa, 0x55, 0); + } + } else { /* Monochrome LCD */ + for (int c = 0; c < 256; c++) { + int cval = 0; + if (c & 0x0f) + cval = ((c & 0x0e) * 0x10) + 0x1f; + pallook64[c] = makecol32(cval, cval, cval); + pallook16[c] = makecol32(cval, cval, cval); + } + } + jega_recalctimings(jega); + } else if (p65idx == 0x05) { + if (val & 0x10) { /* Power off (instead this call hardware reset here) */ + resetx86(); + } + } + } + return; +} + +static void * +if386jega_init(const device_t *info) +{ + jega_t *jega = calloc(1, sizeof(jega_t)); + + rom_init(&jega->bios_rom, IF386_PATH_VBIOS, 0xc0000, 0x8000, 0x7fff, 0, 0); + memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE); + LoadFontxFile(JEGA_PATH_FONTDBCS, jega); + + jega_commoninit(jega); + + io_sethandler(0x0063, 1, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega); + io_sethandler(0x0065, 1, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega); + // io_sethandler(0x03dd, 2, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega); + + return jega; +} + +static int +if386jega_available(void) +{ + return (rom_present(IF386_PATH_VBIOS) && rom_present(JEGA_PATH_FONTDBCS)); +} + +const device_t if386jega_device = { + .name = "JEGA (if386AX)", + .internal_name = "if386jega", + .flags = DEVICE_ISA, + .local = 0, + .init = if386jega_init, + .close = jega_close, + .reset = NULL, + .available = if386jega_available, .speed_changed = jega_speed_changed, .force_redraw = NULL, .config = NULL