diff --git a/src/keyboard_xt.c b/src/keyboard_xt.c index 7d6c5def4..197297d67 100644 --- a/src/keyboard_xt.c +++ b/src/keyboard_xt.c @@ -8,7 +8,7 @@ * * Implementation of the XT-style keyboard. * - * Version: @(#)keyboard_xt.c 1.0.3 2017/11/06 + * Version: @(#)keyboard_xt.c 1.0.4 2017/11/10 * * Authors: Sarah Walker, * Miran Grca, @@ -33,7 +33,6 @@ #include "rom.h" #include "timer.h" #include "device.h" -#include "tandy_eeprom.h" #include "sound/sound.h" #include "sound/snd_speaker.h" #include "video/video.h" @@ -217,10 +216,10 @@ kbd_poll(void *priv) kbd->pa = key_queue[key_queue_start]; picint(2); #if ENABLE_KEYBOARD_LOG - pclog("Reading %02X from the key queue at %i\n", + pclog("XTkbd: reading %02X from the key queue at %i\n", kbd->pa, key_queue_start); #endif - key_queue_start = (key_queue_start + 1) & 0xf; + key_queue_start = (key_queue_start + 1) & 0x0f; kbd->blocked = 1; } } @@ -234,7 +233,7 @@ kbd_adddata(uint8_t val) pclog("XTkbd: %02X added to key queue at %i\n", val, key_queue_end); #endif - key_queue_end = (key_queue_end + 1) & 0xf; + key_queue_end = (key_queue_end + 1) & 0x0f; } @@ -283,11 +282,11 @@ kbd_read(uint16_t port, void *priv) case 0x60: if ((romset == ROM_IBMPC) && (kbd->pb & 0x80)) { if (VGA || gfxcard == GFX_EGA) - ret = 0x4D; + ret = 0x4d; else if (MDA) - ret = 0x7D; + ret = 0x7d; else - ret = 0x6D; + ret = 0x6d; } else ret = kbd->pa; break; @@ -299,7 +298,7 @@ kbd_read(uint16_t port, void *priv) case 0x62: if (romset == ROM_IBMPC) { if (kbd->pb & 0x04) - ret = ((mem_size-64) / 32) & 0xf; + ret = ((mem_size-64) / 32) & 0x0f; else ret = ((mem_size-64) / 32) >> 4; } else { @@ -311,16 +310,16 @@ kbd_read(uint16_t port, void *priv) else ret = 6; } else - ret = 0x0D; + ret = 0x0d; } ret |= (ppispeakon ? 0x20 : 0); if (kbd->tandy) - ret |= (tandy_eeprom_read() ? 0x10 : 0); + ret |= (tandy1k_eeprom_read() ? 0x10 : 0); break; default: - pclog("\nXTkbd: bad read %04X\n", port); + pclog("XTkbd: bad read %04X\n", port); ret = 0xff; } diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 8a6d8151c..74b567176 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -1,125 +1,1611 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of Tandy models 1000, 1000HX and 1000SL2. + * + * Version: @(#)m_tandy.c 1.0.1 2017/11/10 + * + * Authors: Sarah Walker, + * Miran Grca, + * + * Copyright 2008-2017 Sarah Walker. + * Copyright 2016,2017 Miran Grca. + */ #include #include +#include #include #include +#include #include "../86box.h" +#include "../io.h" +#include "../pit.h" #include "../nmi.h" #include "../mem.h" #include "../rom.h" +#include "../timer.h" #include "../device.h" +#include "../nvr.h" #include "../game/gameport.h" #include "../keyboard.h" -#include "../tandy_eeprom.h" -#include "../tandy_rom.h" #include "../sound/sound.h" #include "../sound/snd_pssj.h" #include "../sound/snd_sn76489.h" +#include "../video/video.h" +#include "../video/vid_cga_comp.h" #include "machine.h" -static scancode scancode_tandy[272] = { - { {-1}, {-1} }, { {0x01, -1}, {0x81, -1} }, { {0x02, -1}, {0x82, -1} }, { {0x03, -1}, {0x83, -1} }, - { {0x04, -1}, {0x84, -1} }, { {0x05, -1}, {0x85, -1} }, { {0x06, -1}, {0x86, -1} }, { {0x07, -1}, {0x87, -1} }, - { {0x08, -1}, {0x88, -1} }, { {0x09, -1}, {0x89, -1} }, { {0x0a, -1}, {0x8a, -1} }, { {0x0b, -1}, {0x8b, -1} }, - { {0x0c, -1}, {0x8c, -1} }, { {0x0d, -1}, {0x8d, -1} }, { {0x0e, -1}, {0x8e, -1} }, { {0x0f, -1}, {0x8f, -1} }, - { {0x10, -1}, {0x90, -1} }, { {0x11, -1}, {0x91, -1} }, { {0x12, -1}, {0x92, -1} }, { {0x13, -1}, {0x93, -1} }, - { {0x14, -1}, {0x94, -1} }, { {0x15, -1}, {0x95, -1} }, { {0x16, -1}, {0x96, -1} }, { {0x17, -1}, {0x97, -1} }, - { {0x18, -1}, {0x98, -1} }, { {0x19, -1}, {0x99, -1} }, { {0x1a, -1}, {0x9a, -1} }, { {0x1b, -1}, {0x9b, -1} }, - { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, { {0x1e, -1}, {0x9e, -1} }, { {0x1f, -1}, {0x9f, -1} }, - { {0x20, -1}, {0xa0, -1} }, { {0x21, -1}, {0xa1, -1} }, { {0x22, -1}, {0xa2, -1} }, { {0x23, -1}, {0xa3, -1} }, - { {0x24, -1}, {0xa4, -1} }, { {0x25, -1}, {0xa5, -1} }, { {0x26, -1}, {0xa6, -1} }, { {0x27, -1}, {0xa7, -1} }, - { {0x28, -1}, {0xa8, -1} }, { {0x29, -1}, {0xa9, -1} }, { {0x2a, -1}, {0xaa, -1} }, { {0x47, -1}, {0xc7, -1} }, - { {0x2c, -1}, {0xac, -1} }, { {0x2d, -1}, {0xad, -1} }, { {0x2e, -1}, {0xae, -1} }, { {0x2f, -1}, {0xaf, -1} }, - { {0x30, -1}, {0xb0, -1} }, { {0x31, -1}, {0xb1, -1} }, { {0x32, -1}, {0xb2, -1} }, { {0x33, -1}, {0xb3, -1} }, - { {0x34, -1}, {0xb4, -1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} }, - { {0x38, -1}, {0xb8, -1} }, { {0x39, -1}, {0xb9, -1} }, { {0x3a, -1}, {0xba, -1} }, { {0x3b, -1}, {0xbb, -1} }, - { {0x3c, -1}, {0xbc, -1} }, { {0x3d, -1}, {0xbd, -1} }, { {0x3e, -1}, {0xbe, -1} }, { {0x3f, -1}, {0xbf, -1} }, - { {0x40, -1}, {0xc0, -1} }, { {0x41, -1}, {0xc1, -1} }, { {0x42, -1}, {0xc2, -1} }, { {0x43, -1}, {0xc3, -1} }, - { {0x44, -1}, {0xc4, -1} }, { {0x45, -1}, {0xc5, -1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} }, - { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, { {0x4a, -1}, {0xca, -1} }, { {0x4b, -1}, {0xcb, -1} }, - { {0x4c, -1}, {0xcc, -1} }, { {0x4d, -1}, {0xcd, -1} }, { {0x4e, -1}, {0xce, -1} }, { {0x4f, -1}, {0xcf, -1} }, - { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x56, -1}, {0xd6, -1} }, - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*54*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*58*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*5c*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*60*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*64*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*68*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*6c*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*70*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*74*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*78*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*7c*/ +#define TANDY_RGB 0 +#define TANDY_COMPOSITE 1 - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*80*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*84*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*88*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*8c*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*90*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*94*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*98*/ - { {0x57, -1}, {0xd7, -1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*9c*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*a0*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*a4*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {0xaa, -1}, {0x2a, -1} }, { {-1}, {-1} }, /*a8*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*ac*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*b0*/ - { {-1}, {-1} }, { {0x35, -1}, {0xb5, -1} }, { {0xb6, -1}, {0x36, -1} }, { {0x37, -1}, {0xb7, -1} }, /*b4*/ - { {0x38, -1}, {0xb8, -1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*b8*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*bc*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*c0*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} }, /*c4*/ - { {0x29, -1}, {0xa9, -1} }, { {0x49, -1}, {0xc9, -1} }, { {-1}, {-1} }, { {0x2b, -1}, {0xab, -1} }, /*c8*/ - { {-1}, {-1} }, { {0x4e, -1}, {0xce, -1} }, { {-1}, {-1} }, { {0x4f, -1}, {0xcf, -1} }, /*cc*/ - { {0x4a, -1}, {0xca, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} }, /*d0*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*d4*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*d8*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*dc*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e0*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e4*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e8*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*ec*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f0*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f4*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f8*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*fc*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*100*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*104*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*108*/ - { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*10c*/ + +enum { + EEPROM_IDLE = 0, + EEPROM_GET_OPERATION, + EEPROM_READ, + EEPROM_WRITE }; +typedef struct { + mem_mapping_t mapping; + mem_mapping_t vram_mapping; + + uint8_t crtc[32]; + int crtcreg; + + int array_index; + uint8_t array[32]; + int memctrl; + uint8_t mode, col; + uint8_t stat; + + uint8_t *vram, *b8000; + uint32_t b8000_mask; + uint32_t b8000_limit; + uint8_t planar_ctrl; + + int linepos, + displine; + int sc, vc; + int dispon; + int con, coff, + cursoron, + blink; + int64_t vsynctime; + int vadj; + uint16_t ma, maback; + + int64_t dispontime, + dispofftime, + vidtime; + int firstline, + lastline; + + int composite; +} t1kvid_t; + +typedef struct { + int romset; + wchar_t *path; + + int state; + int count; + int addr; + int clk; + uint16_t data; + uint16_t store[64]; +} t1keep_t; + +typedef struct { + mem_mapping_t ram_mapping; + mem_mapping_t rom_mapping; /* SL2 */ + + uint8_t *rom; /* SL2 */ + uint8_t ram_bank; + uint8_t rom_bank; /* SL2 */ + int rom_offset; /* SL2 */ + + uint32_t base; + int is_sl2; + + t1kvid_t *vid; +} tandy_t; + + +static scancode scancode_tandy[272] = { + { {-1}, {-1} }, { {0x01, -1}, {0x81, -1} }, + { {0x02, -1}, {0x82, -1} }, { {0x03, -1}, {0x83, -1} }, + { {0x04, -1}, {0x84, -1} }, { {0x05, -1}, {0x85, -1} }, + { {0x06, -1}, {0x86, -1} }, { {0x07, -1}, {0x87, -1} }, + { {0x08, -1}, {0x88, -1} }, { {0x09, -1}, {0x89, -1} }, + { {0x0a, -1}, {0x8a, -1} }, { {0x0b, -1}, {0x8b, -1} }, + { {0x0c, -1}, {0x8c, -1} }, { {0x0d, -1}, {0x8d, -1} }, + { {0x0e, -1}, {0x8e, -1} }, { {0x0f, -1}, {0x8f, -1} }, + { {0x10, -1}, {0x90, -1} }, { {0x11, -1}, {0x91, -1} }, + { {0x12, -1}, {0x92, -1} }, { {0x13, -1}, {0x93, -1} }, + { {0x14, -1}, {0x94, -1} }, { {0x15, -1}, {0x95, -1} }, + { {0x16, -1}, {0x96, -1} }, { {0x17, -1}, {0x97, -1} }, + { {0x18, -1}, {0x98, -1} }, { {0x19, -1}, {0x99, -1} }, + { {0x1a, -1}, {0x9a, -1} }, { {0x1b, -1}, {0x9b, -1} }, + { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, + { {0x1e, -1}, {0x9e, -1} }, { {0x1f, -1}, {0x9f, -1} }, + { {0x20, -1}, {0xa0, -1} }, { {0x21, -1}, {0xa1, -1} }, + { {0x22, -1}, {0xa2, -1} }, { {0x23, -1}, {0xa3, -1} }, + { {0x24, -1}, {0xa4, -1} }, { {0x25, -1}, {0xa5, -1} }, + { {0x26, -1}, {0xa6, -1} }, { {0x27, -1}, {0xa7, -1} }, + { {0x28, -1}, {0xa8, -1} }, { {0x29, -1}, {0xa9, -1} }, + { {0x2a, -1}, {0xaa, -1} }, { {0x47, -1}, {0xc7, -1} }, + { {0x2c, -1}, {0xac, -1} }, { {0x2d, -1}, {0xad, -1} }, + { {0x2e, -1}, {0xae, -1} }, { {0x2f, -1}, {0xaf, -1} }, + { {0x30, -1}, {0xb0, -1} }, { {0x31, -1}, {0xb1, -1} }, + { {0x32, -1}, {0xb2, -1} }, { {0x33, -1}, {0xb3, -1} }, + { {0x34, -1}, {0xb4, -1} }, { {0x35, -1}, {0xb5, -1} }, + { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} }, + { {0x38, -1}, {0xb8, -1} }, { {0x39, -1}, {0xb9, -1} }, + { {0x3a, -1}, {0xba, -1} }, { {0x3b, -1}, {0xbb, -1} }, + { {0x3c, -1}, {0xbc, -1} }, { {0x3d, -1}, {0xbd, -1} }, + { {0x3e, -1}, {0xbe, -1} }, { {0x3f, -1}, {0xbf, -1} }, + { {0x40, -1}, {0xc0, -1} }, { {0x41, -1}, {0xc1, -1} }, + { {0x42, -1}, {0xc2, -1} }, { {0x43, -1}, {0xc3, -1} }, + { {0x44, -1}, {0xc4, -1} }, { {0x45, -1}, {0xc5, -1} }, + { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} }, + { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, + { {0x4a, -1}, {0xca, -1} }, { {0x4b, -1}, {0xcb, -1} }, + { {0x4c, -1}, {0xcc, -1} }, { {0x4d, -1}, {0xcd, -1} }, + { {0x4e, -1}, {0xce, -1} }, { {0x4f, -1}, {0xcf, -1} }, + { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, + { {0x52, -1}, {0xd2, -1} }, { {0x56, -1}, {0xd6, -1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {0x57, -1}, {0xd7, -1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {0xaa, -1}, {0x2a, -1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {0x35, -1}, {0xb5, -1} }, + { {0xb6, -1}, {0x36, -1} }, { {0x37, -1}, {0xb7, -1} }, + { {0x38, -1}, {0xb8, -1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} }, + { {0x29, -1}, {0xa9, -1} }, { {0x49, -1}, {0xc9, -1} }, + { {-1}, {-1} }, { {0x2b, -1}, {0xab, -1} }, + { {-1}, {-1} }, { {0x4e, -1}, {0xce, -1} }, + { {-1}, {-1} }, { {0x4f, -1}, {0xcf, -1} }, + { {0x4a, -1}, {0xca, -1} }, { {0x51, -1}, {0xd1, -1} }, + { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} }, + { {-1}, {-1} }, { {-1}, {-1} } +}; +static uint8_t crtcmask[32] = { + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, + 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static uint8_t crtcmask_sl[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, + 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static int eep_data_out; + + +static uint8_t vid_in(uint16_t addr, void *priv); +static void vid_out(uint16_t addr, uint8_t val, void *priv); + +static void +recalc_mapping(tandy_t *dev) +{ + t1kvid_t *vid = dev->vid; + + mem_mapping_disable(&vid->mapping); + io_removehandler(0x03d0, 16, + vid_in, NULL, NULL, vid_out, NULL, NULL, dev); + + if (vid->planar_ctrl & 4) { + mem_mapping_enable(&vid->mapping); + if (vid->array[5] & 1) + mem_mapping_set_addr(&vid->mapping, 0xa0000, 0x10000); + else + mem_mapping_set_addr(&vid->mapping, 0xb8000, 0x8000); + io_sethandler(0x03d0, 16, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + } +} + + +static void +recalc_timings(tandy_t *dev) +{ + t1kvid_t *vid = dev->vid; + + double _dispontime, _dispofftime, disptime; + + if (vid->mode & 1) { + disptime = vid->crtc[0] + 1; + _dispontime = vid->crtc[1]; + } else { + disptime = (vid->crtc[0] + 1) << 1; + _dispontime = vid->crtc[1] << 1; + } + + _dispofftime = disptime - _dispontime; + _dispontime *= CGACONST; + _dispofftime *= CGACONST; + vid->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + vid->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); +} + + +static void +recalc_address(tandy_t *dev) +{ + t1kvid_t *vid = dev->vid; + + if ((vid->memctrl & 0xc0) == 0xc0) { + vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base]; + vid->b8000_mask = 0x7fff; + } else { + vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base]; + vid->b8000_mask = 0x3fff; + } +} + + +static void +recalc_address_sl(tandy_t *dev) +{ + t1kvid_t *vid = dev->vid; + + vid->b8000_limit = 0x8000; + + if (vid->array[5] & 1) { + vid->vram = &ram[((vid->memctrl & 0x04) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x20) << 11) + dev->base]; + } else if ((vid->memctrl & 0xc0) == 0xc0) { + vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base]; + } else { + vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base]; + vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base]; + if ((vid->memctrl & 0x38) == 0x38) + vid->b8000_limit = 0x4000; + } +} + + +static void +vid_out(uint16_t addr, uint8_t val, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + t1kvid_t *vid = dev->vid; + uint8_t old; + + switch (addr) { + case 0x03d4: + vid->crtcreg = val & 0x1f; + break; + + case 0x03d5: + old = vid->crtc[vid->crtcreg]; + if (dev->is_sl2) + vid->crtc[vid->crtcreg] = val & crtcmask_sl[vid->crtcreg]; + else + vid->crtc[vid->crtcreg] = val & crtcmask[vid->crtcreg]; + if (old != val) { + if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) { + fullchange = changeframecount; + recalc_timings(dev); + } + } + break; + + case 0x03d8: + vid->mode = val; + if (! dev->is_sl2) + update_cga16_color(vid->mode); + break; + + case 0x03d9: + vid->col = val; + break; + + case 0x03da: + vid->array_index = val & 0x1f; + break; + + case 0x03de: + if (vid->array_index & 16) + val &= 0xf; + vid->array[vid->array_index & 0x1f] = val; + if (dev->is_sl2) { + if ((vid->array_index & 0x1f) == 5) { + recalc_mapping(dev); + recalc_address_sl(dev); + } + } + break; + + case 0x03df: + vid->memctrl = val; + if (dev->is_sl2) + recalc_address_sl(dev); + else + recalc_address(dev); + break; + + case 0x0065: + if (val == 8) return; /*Hack*/ + vid->planar_ctrl = val; + recalc_mapping(dev); + break; + } +} + + +static uint8_t +vid_in(uint16_t addr, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + t1kvid_t *vid = dev->vid; + uint8_t ret = 0xff; + + switch (addr) { + case 0x03d4: + ret = vid->crtcreg; + break; + + case 0x03d5: + ret = vid->crtc[vid->crtcreg]; + break; + + case 0x03da: + ret = vid->stat; + break; + } + + return(ret); +} + + +static void +vid_write(uint32_t addr, uint8_t val, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + t1kvid_t *vid = dev->vid; + + if (vid->memctrl == -1) return; + + egawrites++; + if (dev->is_sl2) { + if (vid->array[5] & 1) + vid->b8000[addr & 0xffff] = val; + else { + if ((addr & 0x7fff) < vid->b8000_limit) + vid->b8000[addr & 0x7fff] = val; + } + } else { + vid->b8000[addr & vid->b8000_mask] = val; + } +} + + +static uint8_t +vid_read(uint32_t addr, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + t1kvid_t *vid = dev->vid; + + if (vid->memctrl == -1) return(0xff); + + egareads++; + if (dev->is_sl2) { + if (vid->array[5] & 1) + return(vid->b8000[addr & 0xffff]); + if ((addr & 0x7fff) < vid->b8000_limit) + return(vid->b8000[addr & 0x7fff]); + else + return(0xff); + } else { + return(vid->b8000[addr & vid->b8000_mask]); + } +} + + +static void +vid_poll(void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + t1kvid_t *vid = dev->vid; + uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x, c; + int oldvc; + uint8_t chr, attr; + uint16_t dat; + int cols[4]; + int col; + int oldsc; + + if (! vid->linepos) { + vid->vidtime += vid->dispofftime; + vid->stat |= 1; + vid->linepos = 1; + oldsc = vid->sc; + if ((vid->crtc[8] & 3) == 3) + vid->sc = (vid->sc << 1) & 7; + + if (vid->dispon) { + if (vid->displine < vid->firstline) { + vid->firstline = vid->displine; + video_wait_for_buffer(); + } + vid->lastline = vid->displine; + cols[0] = (vid->array[2] & 0xf) + 16; + for (c = 0; c < 8; c++) { + if (vid->array[3] & 4) { + buffer->line[vid->displine][c] = cols[0]; + if (vid->mode & 1) + buffer->line[vid->displine][c + (vid->crtc[1] << 3) + 8] = cols[0]; + else + buffer->line[vid->displine][c + (vid->crtc[1] << 4) + 8] = cols[0]; + } else if ((vid->mode & 0x12) == 0x12) { + buffer->line[vid->displine][c] = 0; + if (vid->mode & 1) + buffer->line[vid->displine][c + (vid->crtc[1] << 3) + 8] = 0; + else + buffer->line[vid->displine][c + (vid->crtc[1] << 4) + 8] = 0; + } else { + buffer->line[vid->displine][c] = (vid->col & 15) + 16; + if (vid->mode & 1) + buffer->line[vid->displine][c + (vid->crtc[1] << 3) + 8] = (vid->col & 15) + 16; + else + buffer->line[vid->displine][c + (vid->crtc[1] << 4) + 8] = (vid->col & 15) + 16; + } + } + + if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | + vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; + vid->ma++; + buffer->line[vid->displine][(x << 3) + 8] = + buffer->line[vid->displine][(x << 3) + 9] = vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; + buffer->line[vid->displine][(x << 3) + 10] = + buffer->line[vid->displine][(x << 3) + 11] = vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; + buffer->line[vid->displine][(x << 3) + 12] = + buffer->line[vid->displine][(x << 3) + 13] = vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; + buffer->line[vid->displine][(x << 3) + 14] = + buffer->line[vid->displine][(x << 3) + 15] = vid->array[(dat & vid->array[1]) + 16] + 16; + } + } else if (vid->array[3] & 0x10) { /*160x200x16*/ + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | + vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; + vid->ma++; + buffer->line[vid->displine][(x << 4) + 8] = + buffer->line[vid->displine][(x << 4) + 9] = + buffer->line[vid->displine][(x << 4) + 10] = + buffer->line[vid->displine][(x << 4) + 11] = vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; + buffer->line[vid->displine][(x << 4) + 12] = + buffer->line[vid->displine][(x << 4) + 13] = + buffer->line[vid->displine][(x << 4) + 14] = + buffer->line[vid->displine][(x << 4) + 15] = vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; + buffer->line[vid->displine][(x << 4) + 16] = + buffer->line[vid->displine][(x << 4) + 17] = + buffer->line[vid->displine][(x << 4) + 18] = + buffer->line[vid->displine][(x << 4) + 19] = vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; + buffer->line[vid->displine][(x << 4) + 20] = + buffer->line[vid->displine][(x << 4) + 21] = + buffer->line[vid->displine][(x << 4) + 22] = + buffer->line[vid->displine][(x << 4) + 23] = vid->array[(dat & vid->array[1]) + 16] + 16; + } + } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | + vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; + vid->ma++; + for (c = 0; c < 8; c++) { + chr = (dat >> 7) & 1; + chr |= ((dat >> 14) & 2); + buffer->line[vid->displine][(x << 3) + 8 + c] = vid->array[(chr & vid->array[1]) + 16] + 16; + dat <<= 1; + } + } + } else if (vid->mode & 1) { + for (x = 0; x < vid->crtc[1]; x++) { + chr = vid->vram[ (vid->ma << 1) & 0x3fff]; + attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; + drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); + if (vid->mode & 0x20) { + cols[1] = vid->array[ ((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; + if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; + } + if (vid->sc & 8) { + for (c = 0; c < 8; c++) + buffer->line[vid->displine][(x << 3) + c + 8] = cols[0]; + } else { + for (c = 0; c < 8; c++) + buffer->line[vid->displine][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + if (drawcursor) { + for (c = 0; c < 8; c++) + buffer->line[vid->displine][(x << 3) + c + 8] ^= 15; + } + vid->ma++; + } + } else if (! (vid->mode & 2)) { + for (x = 0; x < vid->crtc[1]; x++) { + chr = vid->vram[ (vid->ma << 1) & 0x3fff]; + attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; + drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); + if (vid->mode & 0x20) { + cols[1] = vid->array[ ((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; + if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; + } + vid->ma++; + if (vid->sc & 8) { + for (c = 0; c < 8; c++) + buffer->line[vid->displine][(x << 4) + (c << 1) + 8] = + buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[0]; + } else { + for (c = 0; c < 8; c++) + buffer->line[vid->displine][(x << 4) + (c << 1) + 8] = + buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + if (drawcursor) { + for (c = 0; c < 16; c++) + buffer->line[vid->displine][(x << 4) + c + 8] ^= 15; + } + } + } else if (! (vid->mode& 16)) { + cols[0] = (vid->col & 15) | 16; + col = (vid->col & 16) ? 24 : 16; + if (vid->mode & 4) { + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; + } else if (vid->col & 32) { + cols[1] = col | 3; + cols[2] = col | 5; + cols[3] = col | 7; + } else { + cols[1] = col | 2; + cols[2] = col | 4; + cols[3] = col | 6; + } + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | + vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; + vid->ma++; + for (c = 0; c < 8; c++) { + buffer->line[vid->displine][(x << 4) + (c << 1) + 8] = + buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; + dat <<= 2; + } + } + } else { + cols[0] = 0; + cols[1] = vid->array[(vid->col & vid->array[1]) + 16] + 16; + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | + vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; + vid->ma++; + for (c = 0; c < 16; c++) { + buffer->line[vid->displine][(x << 4) + c + 8] = cols[dat >> 15]; + dat <<= 1; + } + } + } + } else { + if (vid->array[3] & 4) { + if (vid->mode & 1) + hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); + else + hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); + } else { + cols[0] = ((vid->mode & 0x12) == 0x12) ? 0 : (vid->col & 0xf) + 16; + if (vid->mode & 1) + hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, cols[0]); + else + hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, cols[0]); + } + } + + if (vid->mode & 1) + x = (vid->crtc[1] << 3) + 16; + else + x = (vid->crtc[1] << 4) + 16; + if (vid->composite) { + for (c = 0; c < x; c++) + buffer32->line[vid->displine][c] = buffer->line[vid->displine][c] & 0xf; + + Composite_Process(vid->mode, 0, x >> 2, buffer32->line[vid->displine]); + } + vid->sc = oldsc; + if (vid->vc == vid->crtc[7] && !vid->sc) + vid->stat |= 8; + vid->displine++; + if (vid->displine >= 360) + vid->displine = 0; + } else { + vid->vidtime += vid->dispontime; + if (vid->dispon) + vid->stat &= ~1; + vid->linepos = 0; + if (vid->vsynctime) { + vid->vsynctime--; + if (! vid->vsynctime) + vid->stat &= ~8; + } + if (vid->sc == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[11] & 31) >> 1))) { + vid->con = 0; + vid->coff = 1; + } + if (vid->vadj) { + vid->sc++; + vid->sc &= 31; + vid->ma = vid->maback; + vid->vadj--; + if (! vid->vadj) { + vid->dispon = 1; + vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; + vid->sc = 0; + } + } else if (vid->sc == vid->crtc[9] || ((vid->crtc[8] & 3) == 3 && vid->sc == (vid->crtc[9] >> 1))) { + vid->maback = vid->ma; + vid->sc = 0; + oldvc = vid->vc; + vid->vc++; + vid->vc &= 127; + if (vid->vc == vid->crtc[6]) + vid->dispon = 0; + if (oldvc == vid->crtc[4]) { + vid->vc = 0; + vid->vadj = vid->crtc[5]; + if (! vid->vadj) + vid->dispon = 1; + if (! vid->vadj) + vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; + if ((vid->crtc[10] & 0x60) == 0x20) + vid->cursoron = 0; + else + vid->cursoron = vid->blink & 16; + } + if (vid->vc == vid->crtc[7]) { + vid->dispon = 0; + vid->displine = 0; + vid->vsynctime = 16; + if (vid->crtc[7]) { + if (vid->mode & 1) + x = (vid->crtc[1] << 3) + 16; + else + x = (vid->crtc[1] << 4) + 16; + vid->lastline++; + if ((x != xsize) || ((vid->lastline - vid->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = vid->lastline - vid->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, (ysize << 1) + 16); + if (video_force_resize_get()) + video_force_resize_set(0); + } + if (vid->composite) + video_blit_memtoscreen(0, vid->firstline-4, 0, (vid->lastline - vid->firstline) + 8, xsize, (vid->lastline - vid->firstline) + 8); + else + video_blit_memtoscreen_8(0, vid->firstline-4, 0, (vid->lastline - vid->firstline) + 8, xsize, (vid->lastline - vid->firstline) + 8); + + frames++; + + video_res_x = xsize - 16; + video_res_y = ysize; + if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ + video_res_x /= 2; + video_bpp = 4; + } else if (vid->array[3] & 0x10) { /*160x200x16*/ + video_res_x /= 4; + video_bpp = 4; + } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ + video_bpp = 2; + } else if (vid->mode & 1) { + video_res_x /= 8; + video_res_y /= vid->crtc[9] + 1; + video_bpp = 0; + } else if (! (vid->mode & 2)) { + video_res_x /= 16; + video_res_y /= vid->crtc[9] + 1; + video_bpp = 0; + } else if (! (vid->mode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else { + video_bpp = 1; + } + } + vid->firstline = 1000; + vid->lastline = 0; + vid->blink++; + } + } else { + vid->sc++; + vid->sc &= 31; + vid->ma = vid->maback; + } + if ((vid->sc == (vid->crtc[10] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[10] & 31) >> 1)))) + vid->con = 1; + } +} + + +static void +vid_poll_sl(void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + t1kvid_t *vid = dev->vid; + uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x, c; + int oldvc; + uint8_t chr, attr; + uint16_t dat; + int cols[4]; + int col; + int oldsc; + + if (! vid->linepos) { + vid->vidtime += vid->dispofftime; + vid->stat |= 1; + vid->linepos = 1; + oldsc = vid->sc; + if ((vid->crtc[8] & 3) == 3) + vid->sc = (vid->sc << 1) & 7; + if (vid->dispon) { + if (vid->displine < vid->firstline) { + vid->firstline = vid->displine; + video_wait_for_buffer(); + } + vid->lastline = vid->displine; + cols[0] = (vid->array[2] & 0xf) + 16; + for (c = 0; c < 8; c++) { + if (vid->array[3] & 4) { + buffer->line[vid->displine][c] = cols[0]; + if (vid->mode & 1) + buffer->line[vid->displine][c + (vid->crtc[1] << 3) + 8] = cols[0]; + else + buffer->line[vid->displine][c + (vid->crtc[1] << 4) + 8] = cols[0]; + } else if ((vid->mode & 0x12) == 0x12) { + buffer->line[vid->displine][c] = 0; + if (vid->mode & 1) + buffer->line[vid->displine][c + (vid->crtc[1] << 3) + 8] = 0; + else + buffer->line[vid->displine][c + (vid->crtc[1] << 4) + 8] = 0; + } else { + buffer->line[vid->displine][c] = (vid->col & 15) + 16; + if (vid->mode & 1) + buffer->line[vid->displine][c + (vid->crtc[1] << 3) + 8] = (vid->col & 15) + 16; + else + buffer->line[vid->displine][c + (vid->crtc[1] << 4) + 8] = (vid->col & 15) + 16; + } + } + if (vid->array[5] & 1) { /*640x200x16*/ + for (x = 0; x < vid->crtc[1]*2; x++) { + dat = (vid->vram[(vid->ma << 1) & 0xffff] << 8) | + vid->vram[((vid->ma << 1) + 1) & 0xffff]; + vid->ma++; + buffer->line[vid->displine][(x << 2) + 8] = vid->array[((dat >> 12) & 0xf)/*vid->array[1])*/ + 16] + 16; + buffer->line[vid->displine][(x << 2) + 9] = vid->array[((dat >> 8) & 0xf)/*vid->array[1])*/ + 16] + 16; + buffer->line[vid->displine][(x << 2) + 10] = vid->array[((dat >> 4) & 0xf)/*vid->array[1])*/ + 16] + 16; + buffer->line[vid->displine][(x << 2) + 11] = vid->array[(dat & 0xf)/*vid->array[1])*/ + 16] + 16; + } + } else if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | + vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; + vid->ma++; + buffer->line[vid->displine][(x << 3) + 8] = + buffer->line[vid->displine][(x << 3) + 9] = vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; + buffer->line[vid->displine][(x << 3) + 10] = + buffer->line[vid->displine][(x << 3) + 11] = vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; + buffer->line[vid->displine][(x << 3) + 12] = + buffer->line[vid->displine][(x << 3) + 13] = vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; + buffer->line[vid->displine][(x << 3) + 14] = + buffer->line[vid->displine][(x << 3) + 15] = vid->array[(dat & vid->array[1]) + 16] + 16; + } + } else if (vid->array[3] & 0x10) { /*160x200x16*/ + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | + vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; + vid->ma++; + buffer->line[vid->displine][(x << 4) + 8] = + buffer->line[vid->displine][(x << 4) + 9] = + buffer->line[vid->displine][(x << 4) + 10] = + buffer->line[vid->displine][(x << 4) + 11] = vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; + buffer->line[vid->displine][(x << 4) + 12] = + buffer->line[vid->displine][(x << 4) + 13] = + buffer->line[vid->displine][(x << 4) + 14] = + buffer->line[vid->displine][(x << 4) + 15] = vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; + buffer->line[vid->displine][(x << 4) + 16] = + buffer->line[vid->displine][(x << 4) + 17] = + buffer->line[vid->displine][(x << 4) + 18] = + buffer->line[vid->displine][(x << 4) + 19] = vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; + buffer->line[vid->displine][(x << 4) + 20] = + buffer->line[vid->displine][(x << 4) + 21] = + buffer->line[vid->displine][(x << 4) + 22] = + buffer->line[vid->displine][(x << 4) + 23] = vid->array[(dat & vid->array[1]) + 16] + 16; + } + } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | + vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; + vid->ma++; + for (c = 0; c < 8; c++) { + chr = (dat >> 7) & 1; + chr |= ((dat >> 14) & 2); + buffer->line[vid->displine][(x << 3) + 8 + c] = vid->array[(chr & vid->array[1]) + 16] + 16; + dat <<= 1; + } + } + } else if (vid->mode & 1) { + for (x = 0; x < vid->crtc[1]; x++) { + chr = vid->vram[ (vid->ma << 1) & 0x3fff]; + attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; + drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); + if (vid->mode & 0x20) { + cols[1] = vid->array[ ((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; + if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; + } + if (vid->sc & 8) { + for (c = 0; c < 8; c++) + buffer->line[vid->displine][(x << 3) + c + 8] = cols[0]; + } else { + for (c = 0; c < 8; c++) + buffer->line[vid->displine][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + if (drawcursor) { + for (c = 0; c < 8; c++) + buffer->line[vid->displine][(x << 3) + c + 8] ^= 15; + } + vid->ma++; + } + } else if (! (vid->mode & 2)) { + for (x = 0; x < vid->crtc[1]; x++) { + chr = vid->vram[ (vid->ma << 1) & 0x3fff]; + attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff]; + drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); + if (vid->mode & 0x20) { + cols[1] = vid->array[ ((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16; + if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16; + cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16; + } + vid->ma++; + if (vid->sc & 8) { + for (c = 0; c < 8; c++) + buffer->line[vid->displine][(x << 4) + (c << 1) + 8] = + buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[0]; + } else { + for (c = 0; c < 8; c++) + buffer->line[vid->displine][(x << 4) + (c << 1) + 8] = + buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + if (drawcursor) { + for (c = 0; c < 16; c++) + buffer->line[vid->displine][(x << 4) + c + 8] ^= 15; + } + } + } else if (! (vid->mode & 16)) { + cols[0] = (vid->col & 15) | 16; + col = (vid->col & 16) ? 24 : 16; + if (vid->mode & 4) { + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; + } else if (vid->col & 32) { + cols[1] = col | 3; + cols[2] = col | 5; + cols[3] = col | 7; + } else { + cols[1] = col | 2; + cols[2] = col | 4; + cols[3] = col | 6; + } + + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | + vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; + vid->ma++; + for (c = 0; c < 8; c++) { + buffer->line[vid->displine][(x << 4) + (c << 1) + 8] = + buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; + dat <<= 2; + } + } + } else { + cols[0] = 0; + cols[1] = vid->array[(vid->col & vid->array[1]) + 16] + 16; + for (x = 0; x < vid->crtc[1]; x++) { + dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | + vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; + vid->ma++; + for (c = 0; c < 16; c++) { + buffer->line[vid->displine][(x << 4) + c + 8] = cols[dat >> 15]; + dat <<= 1; + } + } + } + } else { + if (vid->array[3] & 4) { + if (vid->mode & 1) + hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); + else + hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); + } else { + cols[0] = ((vid->mode & 0x12) == 0x12) ? 0 : (vid->col & 0xf) + 16; + if (vid->mode & 1) + hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, cols[0]); + else + hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, cols[0]); + } + } + + if (vid->mode & 1) + x = (vid->crtc[1] << 3) + 16; + else + x = (vid->crtc[1] << 4) + 16; + vid->sc = oldsc; + + if (vid->vc == vid->crtc[7] && !vid->sc) + vid->stat |= 8; + vid->displine++; + if (vid->displine >= 360) + vid->displine = 0; + } else { + vid->vidtime += vid->dispontime; + if (vid->dispon) + vid->stat &= ~1; + vid->linepos = 0; + if (vid->vsynctime) { + vid->vsynctime--; + if (! vid->vsynctime) + vid->stat &= ~8; + } + if (vid->sc == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[11] & 31) >> 1))) { + vid->con = 0; + vid->coff = 1; + } + if (vid->vadj) { + vid->sc++; + vid->sc &= 31; + vid->ma = vid->maback; + vid->vadj--; + if (! vid->vadj) { + vid->dispon = 1; + if (vid->array[5] & 1) + vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); + else + vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; + vid->sc = 0; + } + } else if (vid->sc == vid->crtc[9] || ((vid->crtc[8] & 3) == 3 && vid->sc == (vid->crtc[9] >> 1))) { + vid->maback = vid->ma; + vid->sc = 0; + oldvc = vid->vc; + vid->vc++; + vid->vc &= 255; + if (vid->vc == vid->crtc[6]) + vid->dispon = 0; + if (oldvc == vid->crtc[4]) { + vid->vc = 0; + vid->vadj = vid->crtc[5]; + if (! vid->vadj) + vid->dispon = 1; + if (! vid->vadj) { + if (vid->array[5] & 1) + vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8); + else + vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; + } + if ((vid->crtc[10] & 0x60) == 0x20) + vid->cursoron = 0; + else + vid->cursoron = vid->blink & 16; + } + if (vid->vc == vid->crtc[7]) { + vid->dispon = 0; + vid->displine = 0; + vid->vsynctime = 16; + if (vid->crtc[7]) { + if (vid->mode & 1) + x = (vid->crtc[1] << 3) + 16; + else + x = (vid->crtc[1] << 4) + 16; + vid->lastline++; + if ((x != xsize) || ((vid->lastline - vid->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = vid->lastline - vid->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + + set_screen_size(xsize, (ysize << 1) + 16); + if (video_force_resize_get()) + video_force_resize_set(0); + } + + video_blit_memtoscreen_8(0, vid->firstline-4, 0, (vid->lastline - vid->firstline) + 8, xsize, (vid->lastline - vid->firstline) + 8); + + frames++; + video_res_x = xsize - 16; + video_res_y = ysize; + if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/ + video_res_x /= 2; + video_bpp = 4; + } else if (vid->array[3] & 0x10) { /*160x200x16*/ + video_res_x /= 4; + video_bpp = 4; + } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ + video_bpp = 2; + } else if (vid->mode & 1) { + video_res_x /= 8; + video_res_y /= vid->crtc[9] + 1; + video_bpp = 0; + } else if (! (vid->mode & 2)) { + video_res_x /= 16; + video_res_y /= vid->crtc[9] + 1; + video_bpp = 0; + } else if (! (vid->mode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else { + video_bpp = 1; + } + } + vid->firstline = 1000; + vid->lastline = 0; + vid->blink++; + } + } else { + vid->sc++; + vid->sc &= 31; + vid->ma = vid->maback; + } + if ((vid->sc == (vid->crtc[10] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[10] & 31) >> 1)))) + vid->con = 1; + } +} + + +static void +vid_speed_changed(void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + + recalc_timings(dev); +} + + +static void +vid_close(void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + + free(dev->vid); + dev->vid = NULL; +} + + +static void +vid_init(tandy_t *dev) +{ + int display_type; + t1kvid_t *vid; + + vid = malloc(sizeof(t1kvid_t)); + memset(vid, 0x00, sizeof(t1kvid_t)); + vid->memctrl = -1; + dev->vid = vid; + + display_type = machine_get_config_int("display_type"); + vid->composite = (display_type != TANDY_RGB); + + cga_comp_init(1); + + if (dev->is_sl2) { + vid->b8000_limit = 0x8000; + vid->planar_ctrl = 4; + overscan_x = overscan_y = 16; + + io_sethandler(0x0065, 1, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + + timer_add(vid_poll_sl, &vid->vidtime, TIMER_ALWAYS_ENABLED, dev); + } else { + vid->b8000_mask = 0x3fff; + + timer_add(vid_poll, &vid->vidtime, TIMER_ALWAYS_ENABLED, dev); + } + mem_mapping_add(&vid->mapping, 0xb8000, 0x08000, + vid_read,NULL,NULL, vid_write,NULL,NULL, NULL, 0, dev); + io_sethandler(0x03d0, 16, + vid_in,NULL,NULL, vid_out,NULL,NULL, dev); +} + + +static device_config_t vid_config[] = { + { + "display_type", "Display type", CONFIG_SELECTION, "", TANDY_RGB, + { + { + "RGB", TANDY_RGB + }, + { + "Composite", TANDY_COMPOSITE + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + + +static device_t vid_device = { + "Tandy 1000", + 0, 0, + NULL, vid_close, NULL, + NULL, + vid_speed_changed, + NULL, + NULL, + vid_config +}; + +static device_t vid_device_sl = { + "Tandy 1000SL2", + 0, 1, + NULL, vid_close, NULL, + NULL, + vid_speed_changed, + NULL, + NULL, + NULL +}; + + +static void +eep_write(uint16_t addr, uint8_t val, void *priv) +{ + t1keep_t *eep = (t1keep_t *)priv; + + if ((val & 4) && !eep->clk) switch (eep->state) { + case EEPROM_IDLE: + switch (eep->count) { + case 0: + if (! (val & 3)) + eep->count = 1; + else + eep->count = 0; + break; + + case 1: + if ((val & 3) == 2) + eep->count = 2; + else + eep->count = 0; + break; + + case 2: + if ((val & 3) == 3) + eep->state = EEPROM_GET_OPERATION; + eep->count = 0; + break; + } + break; + + case EEPROM_GET_OPERATION: + eep->data = (eep->data << 1) | (val & 1); + eep->count++; + if (eep->count == 8) { + eep->count = 0; + eep->addr = eep->data & 0x3f; + switch (eep->data & 0xc0) { + case 0x40: + eep->state = EEPROM_WRITE; + break; + + case 0x80: + eep->state = EEPROM_READ; + eep->data = eep->store[eep->addr]; + break; + + default: + eep->state = EEPROM_IDLE; + break; + } + } + break; + + case EEPROM_READ: + eep_data_out = eep->data & 0x8000; + eep->data <<= 1; + eep->count++; + if (eep->count == 16) { + eep->count = 0; + eep->state = EEPROM_IDLE; + } + break; + + case EEPROM_WRITE: + eep->data = (eep->data << 1) | (val & 1); + eep->count++; + if (eep->count == 16) { + eep->count = 0; + eep->state = EEPROM_IDLE; + eep->store[eep->addr] = eep->data; + } + break; + } + + eep->clk = val & 4; +} + + +static void * +eep_init(device_t *info) +{ + t1keep_t *eep; + FILE *f = NULL; + + eep = (t1keep_t *)malloc(sizeof(t1keep_t)); + memset(eep, 0x00, sizeof(t1keep_t)); + eep->romset = romset; + switch (romset) { + case ROM_TANDY1000HX: + eep->path = L"tandy1000hx.bin"; + break; + + case ROM_TANDY1000SL2: + eep->path = L"tandy1000sl2.bin"; + break; + + } + + f = nvr_fopen(eep->path, L"rb"); + if (f != NULL) { + fread(eep->store, 128, 1, f); + (void)fclose(f); + } + + io_sethandler(0x037c, 1, NULL,NULL,NULL, eep_write,NULL,NULL, eep); + + return(eep); +} + + +static void +eep_close(void *priv) +{ + t1keep_t *eep = (t1keep_t *)priv; + FILE *f = NULL; + + f = nvr_fopen(eep->path, L"rb"); + if (f != NULL) { + (void)fwrite(eep->store, 128, 1, f); + (void)fclose(f); + } + + free(eep); +} + + +static device_t eep_device = { + "Tandy 1000 EEPROM", + 0, 0, + eep_init, eep_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + + +static void +tandy_write(uint16_t addr, uint8_t val, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + + switch (addr) { + case 0x00a0: + mem_mapping_set_addr(&dev->ram_mapping, + ((val >> 1) & 7) * 128 * 1024, 0x20000); + dev->ram_bank = val; + break; + + case 0xffe8: + if ((val & 0xe) == 0xe) + mem_mapping_disable(&dev->ram_mapping); + else + mem_mapping_set_addr(&dev->ram_mapping, + ((val >> 1) & 7) * 128 * 1024, + 0x20000); + recalc_address_sl(dev); + dev->ram_bank = val; + break; + + case 0xffea: + dev->rom_bank = val; + dev->rom_offset = ((val ^ 4) & 7) * 0x10000; + mem_mapping_set_exec(&dev->rom_mapping, + &dev->rom[dev->rom_offset]); + } +} + + +static uint8_t +tandy_read(uint16_t addr, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0x00a0: + ret = dev->ram_bank; + break; + + case 0xffe8: + ret = dev->ram_bank; + break; + + case 0xffea: + ret = (dev->rom_bank ^ 0x10); + break; + } + + return(ret); +} + + +static void +write_ram(uint32_t addr, uint8_t val, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + + ram[dev->base + (addr & 0x1ffff)] = val; +} + + +static uint8_t +read_ram(uint32_t addr, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + + return(ram[dev->base + (addr & 0x1ffff)]); +} + + +static uint8_t +read_rom(uint32_t addr, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + uint32_t addr2 = (addr & 0xffff) + dev->rom_offset; + + return(dev->rom[addr2]); +} + + +static uint16_t +read_romw(uint32_t addr, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + uint32_t addr2 = (addr & 0xffff) + dev->rom_offset; + + return(*(uint16_t *)&dev->rom[addr2]); +} + + +static uint32_t +read_roml(uint32_t addr, void *priv) +{ + tandy_t *dev = (tandy_t *)priv; + + return(*(uint32_t *)&dev->rom[addr]); +} + + +static void +init_rom(tandy_t *dev) +{ + dev->rom = (uint8_t *)malloc(0x80000); + +#if 1 + if (! rom_load_interleaved(L"roms/machines/tandy1000sl2/8079047.hu1", + L"roms/machines/tandy1000sl2/8079048.hu2", + 0x000000, 0x80000, 0, dev->rom)) { + pclog("TANDY: unable to load BIOS for 1000/SL2 !\n"); + free(dev->rom); + dev->rom = NULL; + return; + } +#else + f = rom_fopen(L"roms/machines/tandy1000sl2/8079047.hu1", L"rb"); + ff = rom_fopen(L"roms/machines/tandy1000sl2/8079048.hu2", L"rb"); + for (c = 0x0000; c < 0x80000; c += 2) { + dev->rom[c] = getc(f); + dev->rom[c + 1] = getc(ff); + } + fclose(ff); + fclose(f); +#endif + + mem_mapping_add(&dev->rom_mapping, 0xe0000, 0x10000, + read_rom, read_romw, read_roml, NULL, NULL, NULL, + dev->rom, MEM_MAPPING_EXTERNAL, dev); +} + + void machine_tandy1k_init(machine_t *model) { - machine_common_init(model); + tandy_t *dev; - device_add(&keyboard_tandy_device); - keyboard_set_table(scancode_tandy); + dev = malloc(sizeof(tandy_t)); + memset(dev, 0x00, sizeof(tandy_t)); - if (romset == ROM_TANDY) - device_add(&sn76489_device); - else - device_add(&ncr8496_device); - nmi_init(); - if (romset != ROM_TANDY) - device_add(&tandy_eeprom_device); - if (joystick_type != 7) - device_add(&gameport_device); + machine_common_init(model); + + nmi_init(); + + /* + * Base 128K mapping is controlled via ports 0xA0 or + * 0xFFE8 (SL2), so we remove it from the main mapping. + */ + dev->base = (mem_size - 128) * 1024; + mem_mapping_add(&dev->ram_mapping, 0x80000, 0x20000, + read_ram,NULL,NULL, write_ram,NULL,NULL, NULL, 0, dev); + mem_mapping_set_addr(&ram_low_mapping, 0, dev->base); + + device_add(&keyboard_tandy_device); + keyboard_set_table(scancode_tandy); + + switch(romset) { + case ROM_TANDY: + io_sethandler(0x00a0, 1, + tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); + vid_init(dev); + device_add_ex(&vid_device, dev); + device_add(&sn76489_device); + break; + + case ROM_TANDY1000HX: + io_sethandler(0x00a0, 1, + tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); + vid_init(dev); + device_add_ex(&vid_device, dev); + device_add(&ncr8496_device); + device_add(&eep_device); + break; + + case ROM_TANDY1000SL2: + dev->is_sl2 = 1; + init_rom(dev); + io_sethandler(0xffe8, 8, + tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); + vid_init(dev); + device_add_ex(&vid_device_sl, dev); + device_add(&pssj_device); + device_add(&eep_device); + } + + if (joystick_type != 7) + device_add(&gameport_device); + + eep_data_out = 0x0000; } -void -machine_tandy1ksl2_init(machine_t *model) +int +tandy1k_eeprom_read(void) { - machine_common_init(model); - - device_add(&keyboard_tandy_device); - keyboard_set_table(scancode_tandy); - device_add(&pssj_device); - nmi_init(); - device_add(&tandy_rom_device); - device_add(&tandy_eeprom_device); - if (joystick_type != 7) device_add(&gameport_device); + return(eep_data_out); } diff --git a/src/machine/machine.h b/src/machine/machine.h index 874910d32..82fd6791c 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.h 1.0.10 2017/11/08 + * Version: @(#)machine.h 1.0.11 2017/11/10 * * Authors: Sarah Walker, * Miran Grca, @@ -133,11 +133,13 @@ extern void machine_at_r418_init(machine_t *); extern void machine_at_wd76c10_init(machine_t *); +extern void machine_pcjr_init(machine_t *); + extern void machine_ps1_m2011_init(machine_t *); extern void machine_ps1_m2121_init(machine_t *); extern void machine_ps1_m2133_init(machine_t *); -extern void machine_ps2_m30_286_init(machine_t *); +extern void machine_ps2_m30_286_init(machine_t *); extern void machine_ps2_model_50_init(machine_t *); extern void machine_ps2_model_55sx_init(machine_t *); extern void machine_ps2_model_80_init(machine_t *); @@ -149,10 +151,8 @@ extern void machine_europc_init(machine_t *); extern void machine_olim24_init(machine_t *); -extern void machine_pcjr_init(machine_t *); - extern void machine_tandy1k_init(machine_t *); -extern void machine_tandy1ksl2_init(machine_t *); +extern int tandy1k_eeprom_read(void); extern void machine_xt_init(machine_t *); extern void machine_xt_laserxt_init(machine_t *); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 44991314a..5313cf434 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine_table.c 1.0.1 2017/11/08 + * Version: @(#)machine_table.c 1.0.2 2017/11/10 * * Authors: Sarah Walker, * Miran Grca, @@ -42,7 +42,7 @@ machine_t machines[] = { { "[8088] Phoenix XT clone", ROM_PXXT, "pxxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL }, { "[8088] Schneider EuroPC", ROM_EUROPC, "europc", {{"Siemens",cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_HDC | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 0, machine_europc_init, NULL }, { "[8088] Tandy 1000", ROM_TANDY, "tandy", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 128, 640, 128, 0, machine_tandy1k_init, NULL }, - { "[8088] Tandy 1000 HX", ROM_TANDY1000HX, "tandy1000hx", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 256, 640, 128, 0, machine_tandy1k_init, NULL }, + { "[8088] Tandy 1000HX", ROM_TANDY1000HX, "tandy1000hx", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 256, 640, 128, 0, machine_tandy1k_init, NULL }, { "[8088] VTech Laser Turbo XT", ROM_LTXT, "ltxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 1152, 64, 0, machine_xt_laserxt_init, NULL }, { "[8088] VTech Laser XT3", ROM_LXT3, "lxt3", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 1152, 64, 0, machine_xt_laserxt_init, NULL }, @@ -52,7 +52,7 @@ machine_t machines[] = { { "[8086] Amstrad PC3086", ROM_PC3086, "pc3086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_amstrad_init, NULL }, { "[8086] Amstrad PC20(0)", ROM_PC200, "pc200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_amstrad_init, NULL }, { "[8086] Olivetti M24", ROM_OLIM24, "olivetti_m24", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, machine_olim24_init, NULL }, - { "[8086] Tandy 1000 SL/2", ROM_TANDY1000SL2, "tandy1000sl2", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 512, 768, 128, 0, machine_tandy1ksl2_init, NULL }, + { "[8086] Tandy 1000SL/2", ROM_TANDY1000SL2, "tandy1000sl2", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 512, 768, 128, 0, machine_tandy1k_init, NULL }, { "[286 ISA] AMI 286 clone", ROM_AMI286, "ami286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_neat_init, NULL }, { "[286 ISA] Award 286 clone", ROM_AWARD286, "award286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_scat_init, NULL }, diff --git a/src/tandy_eeprom.c b/src/tandy_eeprom.c deleted file mode 100644 index 7d6d61cbd..000000000 --- a/src/tandy_eeprom.c +++ /dev/null @@ -1,188 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#include -#include -#include -#include -#include -#include "machine/machine.h" -#include "device.h" -#include "mem.h" -#include "rom.h" -#include "io.h" -#include "nvr.h" -#include "tandy_eeprom.h" - - -typedef struct -{ - int state; - int count; - int addr; - int clock; - uint16_t data; - uint16_t store[64]; - - int romset; -} tandy_eeprom_t; - -enum -{ - EEPROM_IDLE, - EEPROM_GET_OPERATION, - EEPROM_READ, - EEPROM_WRITE -}; - - -static int eeprom_data_out; - - -void tandy_eeprom_write(uint16_t addr, uint8_t val, void *p) -{ - tandy_eeprom_t *eeprom = (tandy_eeprom_t *)p; - - if ((val & 4) && !eeprom->clock) - { - switch (eeprom->state) - { - case EEPROM_IDLE: - switch (eeprom->count) - { - case 0: - if (!(val & 3)) - eeprom->count = 1; - else - eeprom->count = 0; - break; - case 1: - if ((val & 3) == 2) - eeprom->count = 2; - else - eeprom->count = 0; - break; - case 2: - if ((val & 3) == 3) - eeprom->state = EEPROM_GET_OPERATION; - eeprom->count = 0; - break; - } - break; - case EEPROM_GET_OPERATION: - eeprom->data = (eeprom->data << 1) | (val & 1); - eeprom->count++; - if (eeprom->count == 8) - { - eeprom->count = 0; - eeprom->addr = eeprom->data & 0x3f; - switch (eeprom->data & 0xc0) - { - case 0x40: - eeprom->state = EEPROM_WRITE; - break; - case 0x80: - eeprom->state = EEPROM_READ; - eeprom->data = eeprom->store[eeprom->addr]; - break; - default: - eeprom->state = EEPROM_IDLE; - break; - } - } - break; - - case EEPROM_READ: - eeprom_data_out = eeprom->data & 0x8000; - eeprom->data <<= 1; - eeprom->count++; - if (eeprom->count == 16) - { - eeprom->count = 0; - eeprom->state = EEPROM_IDLE; - } - break; - case EEPROM_WRITE: - eeprom->data = (eeprom->data << 1) | (val & 1); - eeprom->count++; - if (eeprom->count == 16) - { - eeprom->count = 0; - eeprom->state = EEPROM_IDLE; - eeprom->store[eeprom->addr] = eeprom->data; - } - break; - } - } - - eeprom->clock = val & 4; -} - - -int tandy_eeprom_read(void) -{ - return eeprom_data_out; -} - - -static void *tandy_eeprom_init(device_t *info) -{ - tandy_eeprom_t *eeprom = malloc(sizeof(tandy_eeprom_t)); - FILE *f = NULL; - - memset(eeprom, 0, sizeof(tandy_eeprom_t)); - - eeprom->romset = romset; - switch (romset) - { - case ROM_TANDY1000HX: - f = nvr_fopen(L"tandy1000hx.bin", L"rb"); - break; - case ROM_TANDY1000SL2: - f = nvr_fopen(L"tandy1000sl2.bin", L"rb"); - break; - } - if (f) - { - fread(eeprom->store, 128, 1, f); - fclose(f); - } - else - memset(eeprom->store, 0, 128); - - io_sethandler(0x037c, 0x0001, NULL, NULL, NULL, tandy_eeprom_write, NULL, NULL, eeprom); - - return eeprom; -} - - -void tandy_eeprom_close(void *p) -{ - tandy_eeprom_t *eeprom = (tandy_eeprom_t *)p; - FILE *f = NULL; - - switch (eeprom->romset) - { - case ROM_TANDY1000HX: - f = nvr_fopen(L"tandy1000hx.bin", L"wb"); - break; - case ROM_TANDY1000SL2: - f = nvr_fopen(L"tandy1000sl2.bin", L"wb"); - break; - } - fwrite(eeprom->store, 128, 1, f); - fclose(f); - - free(eeprom); -} - - -device_t tandy_eeprom_device = -{ - "Tandy EEPROM", - 0, 0, - tandy_eeprom_init, - tandy_eeprom_close, - NULL, NULL, NULL, NULL, NULL, - NULL -}; diff --git a/src/tandy_eeprom.h b/src/tandy_eeprom.h deleted file mode 100644 index 5ec491a67..000000000 --- a/src/tandy_eeprom.h +++ /dev/null @@ -1,7 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -device_t tandy_eeprom_device; - - -extern int tandy_eeprom_read(void); diff --git a/src/tandy_rom.c b/src/tandy_rom.c deleted file mode 100644 index e049e0dd9..000000000 --- a/src/tandy_rom.c +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#include -#include -#include -#include -#include -#include "device.h" -#include "io.h" -#include "mem.h" -#include "rom.h" -#include "tandy_rom.h" - - -static uint8_t *tandy_rom; -static uint8_t tandy_rom_bank; -static int tandy_rom_offset; -static mem_mapping_t tandy_rom_mapping; - - -uint8_t tandy_read_rom(uint32_t addr, void *p) -{ - uint32_t addr2 = (addr & 0xffff) + tandy_rom_offset; - return tandy_rom[addr2]; -} - - -uint16_t tandy_read_romw(uint32_t addr, void *p) -{ - uint32_t addr2 = (addr & 0xffff) + tandy_rom_offset; - return *(uint16_t *)&tandy_rom[addr2]; -} - - -uint32_t tandy_read_roml(uint32_t addr, void *p) -{ - return *(uint32_t *)&tandy_rom[addr]; -} - - -uint8_t tandy_rom_bank_read(uint16_t port, void *p) -{ - if (port == 0xffea) - return tandy_rom_bank ^ 0x10; - else - return 0xff; -} - - -void tandy_rom_bank_write(uint16_t port, uint8_t val, void *p) -{ - if (port == 0xffea) - { - tandy_rom_bank = val; - tandy_rom_offset = ((val ^ 4) & 7) * 0x10000; - mem_mapping_set_exec(&tandy_rom_mapping, &tandy_rom[tandy_rom_offset]); - } -} - - -void *tandy_rom_init(device_t *info) -{ - FILE *f, *ff; - int c; - - tandy_rom = malloc(0x80000); - - f = rom_fopen(L"roms/machines/tandy1000sl2/8079047.hu1", L"rb"); - ff = rom_fopen(L"roms/machines/tandy1000sl2/8079048.hu2", L"rb"); - for (c = 0x0000; c < 0x80000; c += 2) - { - tandy_rom[c] = getc(f); - tandy_rom[c + 1] = getc(ff); - } - fclose(ff); - fclose(f); - - mem_mapping_add(&tandy_rom_mapping, 0xe0000, 0x10000, - tandy_read_rom, tandy_read_romw, tandy_read_roml, - NULL, NULL, NULL, - tandy_rom, MEM_MAPPING_EXTERNAL, NULL); - - io_sethandler(0xffe8, 0x0008, tandy_rom_bank_read, NULL, NULL, tandy_rom_bank_write, NULL, NULL, NULL); - - return tandy_rom; -} - - -void tandy_rom_close(void *p) -{ - free(p); -} - - -device_t tandy_rom_device = -{ - "Tandy 1000SL/2 ROM", - 0, 0, - tandy_rom_init, tandy_rom_close, NULL, - NULL, NULL, NULL, NULL, - NULL -}; diff --git a/src/tandy_rom.h b/src/tandy_rom.h deleted file mode 100644 index 252ad206c..000000000 --- a/src/tandy_rom.h +++ /dev/null @@ -1,4 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -extern device_t tandy_rom_device; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index b41a4086e..72f1522d5 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.73 2017/11/08 +# Version: @(#)Makefile.mingw 1.0.74 2017/11/10 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -294,7 +294,6 @@ MCHOBJ := machine.o machine_table.o \ m_ps2_isa.o m_ps2_mca.o DEVOBJ := bugger.o lpt.o $(SERIAL) \ - tandy_eeprom.o tandy_rom.o \ sio_detect.o \ sio_fdc37c66x.o sio_fdc37c669.o \ sio_fdc37c93x.o \