From 0315a8b918394c436f86d59510647873ac591ad5 Mon Sep 17 00:00:00 2001 From: Curt Coder Date: Sun, 2 Apr 2023 13:06:35 +0300 Subject: abc80: Emulate the TKN 80 80-column expansion kit. [Curt Coder] abc80: Add system ROMs with checksum 10042. [PC/M] --- src/mame/luxor/abc80.cpp | 312 +++++++++++++++++++++++++++++++++++++++------ src/mame/luxor/abc80.h | 56 +++++++- src/mame/luxor/abc80_v.cpp | 302 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 569 insertions(+), 101 deletions(-) diff --git a/src/mame/luxor/abc80.cpp b/src/mame/luxor/abc80.cpp index 66eb4a45d55..f2e4f4b4e4b 100644 --- a/src/mame/luxor/abc80.cpp +++ b/src/mame/luxor/abc80.cpp @@ -24,15 +24,15 @@ PCB Layout | | Z80A PIO | | Z80A | | | |--------------| |------------| LS04 LS74A LS86 LS161 LS166 74393 | | | -| ROM3 LS107 4116 4116 LS10 LS257 LS74A LS08 LS107 PROM2 | +| ROM0 LS107 4116 4116 LS10 LS257 LS74A LS08 LS107 PROM2 | | | | ROM2 LS257 4116 4116 LS139 74393 LS107 LS32 LS175 74393 | | | | ROM1 LS257 4116 4116 LS08 LS283 LS10 LS32 PROM1 74393 | | | -| ROM0 LS257 4116 4116 LS257 74393 LS375 74S263 LS145 PROM4 | +| ROM3 LS257 4116 4116 LS257 74393 LS375 74S263 LS145 PROM4 | | | -| DIPSW1 DIPSW2 4045 4045 LS257 LS245 LS375 LS273 LS166 PROM3 | +| SB1 SB2 4045 4045 LS257 LS245 LS375 LS273 LS166 PROM3 | |--------------------------------------------------------------------------------------| Notes: @@ -56,14 +56,74 @@ Notes: CN5 - cassette connector CN6 - keyboard connector SW1 - reset switch - DIPSW1 - - DIPSW2 - - -ROM checksum program: - 10 FOR I%=0% TO 16383% - 20 A%=A%+PEEK(I%) - 30 NEXT I% - 40 ;A%; I% + SB1 - solder bridge for A11/CS1 to ROM1/ROM3 + SB2 - solder bridge for A11/CS1 to ROM0/ROM2 + + +Calculate ROM checksum: + +10 FOR I%=0% TO 16383% +20 A%=A%+PEEK(I%) +30 NEXT I% +40 ;A% +RUN + +*/ + +/* + +Luxor ABC 80 with TKN 80 + +PCB Layout +---------- + +55 10470-02 + + CN1 CN2 CN5 + SW1 |-----| |------------------------| |-----| +|-------| |--| |----------------------------------| |---| +| CN3 CN4 | +| 7912 | +| MC1488 | +| MC1489 7812 | +| LS245 LS138 | +| |-------| | +| |-----CN6-----| LS241 LS241 LS138 LS32 |SN76477| LS04 LM339 | +| |-------| | +| |--------------| |------------| PROM0 LS132 LS273 7406 LS08 | +| | Z80A PIO | | Z80A | | +| |--------------| |------------| LS04 LS74A LS86 LS161 LS166 74393 | +| | +| ROM0 LS107 4116 4116 LS10 LS257 LS74A LS08 LS107 PROM2 | +| | +| ROM2 LS257 4116 4116 LS139 74393 LS107 LS32 LS175 74393 | +| | +| ROM1 LS257 4116 4116 LS08 LS283 LS10 LS32 PROM1 74393 | +|-----------| | +| ROM3 | |------------------------------------------------|LS145 PROM4 | +| |-------| | | +| LS32 LS00 LS257 LS257 LS257 LS00 LS04 LS02 LS51 LS374 |LS166 PROM3 | +| |-----------------| +| ROM4 LS373 LS244 6116 LS74A LS74A LS163 LS163 LS374 | +| LS374 | +|--------------------------------------------------------------------| + +Notes: + All IC's shown. + + PROM0 - MMI 63S141N 512x4 TTL Bipolar PROM + ROM4 - 4Kx8 EPROM "TKN80-III" + 6116 - Hitachi HM6116P-4 2Kx8 Static RAM + + +Switch to 40 column mode: + +;INP(3);CHR$(12) + +Switch to 80 column mode: + +;INP(4);CHR$(12) + */ /* @@ -72,11 +132,11 @@ ROM checksum program: - PWM sound in ABC-klubben/abc80/grafik/flagga.bac - proper keyboard controller emulation - - MyAB TKN80 80-column card - GeJo 80-column card - - Mikrodatorn 64K expansion + - 64K RAM expansions + - Mikrodatorn + - MYAB UNI-80 - Metric ABC CAD 1000 - - ROMs with checksum 10042 */ @@ -128,6 +188,62 @@ u8 abc80_state::read(offs_t offset) return data; } +u8 tkn80_state::read(offs_t offset) +{ + /* + + TKN 000-3ff -> ZA3506 000-3ff (9913/10042) + TKN 400-7ff -> ZA3507 000-3ff (9913/10042) + TKN 800-cff -> ZA3506 000-3ff (11273) + TKN c00-FFF -> ZA3507 000-3ff (11273) + + */ + + u8 data = 0xff; + u8 mmu = m_mmu_rom->base()[0x40 | (offset >> 10)]; + + if (offset < 0x400) + { + if (m_80) + data = m_rom_e->base()[m_rom_offset | (offset & 0x3ff)]; + else + data = m_rom->base()[offset & 0x3fff]; + } + else if (offset >= 0x400 && offset < 0x2000) + { + data = m_rom->base()[offset & 0x3fff]; + } + else if (offset >= 0x2000 && offset < 0x2400) + { + if (m_80) + data = m_rom_e->base()[m_rom_offset | 0x400 | (offset & 0x3ff)]; + else + data = m_rom->base()[offset & 0x3fff]; + } + else if (offset >= 0x2400 && offset < 0x4000) + { + data = m_rom->base()[offset & 0x3fff]; + } + else if (offset >= 0x5800 && offset < 0x6000) + { + data = m_char_ram[offset & 0x7ff]; + } + else if (offset >= 0x7c00 && offset < 0x8000) + { + data = m_char_ram[offset & 0x7ff]; + } + else if (!(mmu & MMU_XM)) + { + data = m_bus->xmemfl_r(offset); + } + else if (!(mmu & MMU_RAM)) + { + data = m_ram->pointer()[offset & 0x3fff]; + } + + return data; +} + //------------------------------------------------- // write - @@ -151,6 +267,28 @@ void abc80_state::write(offs_t offset, u8 data) } } +void tkn80_state::write(offs_t offset, u8 data) +{ + u8 mmu = m_mmu_rom->base()[0x40 | (offset >> 10)]; + + if (offset >= 0x5800 && offset < 0x6000) + { + m_char_ram[offset & 0x7ff] = data; + } + else if (offset >= 0x7c00 && offset < 0x8000) + { + m_char_ram[offset & 0x7ff] = data; + } + else if (!(mmu & MMU_XM)) + { + m_bus->xmemw_w(offset, data); + } + else if (!(mmu & MMU_RAM)) + { + m_ram->pointer()[offset & 0x3fff] = data; + } +} + //************************************************************************** @@ -210,6 +348,41 @@ void abc80_state::abc80_io(address_map &map) } +//------------------------------------------------- +// ADDRESS_MAP( tkn80_io ) +//------------------------------------------------- + +void tkn80_state::tkn80_io(address_map &map) +{ + abc80_io(map); + map(0x03, 0x03).r(FUNC(tkn80_state::in3_r)); + map(0x04, 0x04).r(FUNC(tkn80_state::in4_r)); +} + + + +//************************************************************************** +// INPUT PORTS +//************************************************************************** + +//------------------------------------------------- +// INPUT_PORTS( tkn80 ) +//------------------------------------------------- + +static INPUT_PORTS_START( tkn80 ) + PORT_START("CONFIG") + PORT_CONFNAME( 0x01, 0x01, "Columns" ) + PORT_CONFSETTING( 0x00, "40" ) + PORT_CONFSETTING( 0x01, "80" ) + PORT_CONFNAME( 0x02, 0x02, "Cursor" ) + PORT_CONFSETTING( 0x00, "Static" ) + PORT_CONFSETTING( 0x02, "Blinking" ) + PORT_CONFNAME( 0x04, 0x00, "ROM Checksum" ) + PORT_CONFSETTING( 0x00, "9913/10042" ) + PORT_CONFSETTING( 0x04, "11273" ) +INPUT_PORTS_END + + //************************************************************************** // DEVICE CONFIGURATION @@ -454,12 +627,39 @@ void abc80_state::machine_start() save_item(NAME(m_tape_in)); save_item(NAME(m_tape_in_latch)); - //zero-fill + // zero-fill m_key_data = 0; m_key_strobe = 0; m_blink = 0; } + +void tkn80_state::machine_start() +{ + abc80_state::machine_start(); + + // register for state saving + save_item(NAME(m_80)); + save_item(NAME(m_rom_offset)); +} + + +//------------------------------------------------- +// machine_reset +//------------------------------------------------- + +void tkn80_state::machine_reset() +{ + u8 config = m_config->read(); + + m_rom_offset = BIT(config, 2) << 11; +} + + +//------------------------------------------------- +// QUICKLOAD_LOAD_MEMBER( quickload_cb ) +//------------------------------------------------- + QUICKLOAD_LOAD_MEMBER(abc80_state::quickload_cb) { address_space &space = m_maincpu->space(AS_PROGRAM); @@ -493,10 +693,10 @@ QUICKLOAD_LOAD_MEMBER(abc80_state::quickload_cb) //************************************************************************** //------------------------------------------------- -// machine_config( abc80 ) +// machine_config( abc80_common ) //------------------------------------------------- -void abc80_state::abc80(machine_config &config) +void abc80_state::abc80_common(machine_config &config) { // basic machine hardware Z80(config, m_maincpu, XTAL(11'980'800)/2/2); // 2.9952 MHz @@ -504,9 +704,6 @@ void abc80_state::abc80(machine_config &config) m_maincpu->set_addrmap(AS_IO, &abc80_state::abc80_io); m_maincpu->set_daisy_config(abc80_daisy_chain); - // video hardware - abc80_video(config); - // sound hardware SPEAKER(config, "mono").front_center(); SN76477(config, m_csg); @@ -553,6 +750,30 @@ void abc80_state::abc80(machine_config &config) SOFTWARE_LIST(config, "rom_list").set_original("abc80_rom"); } +void abc80_state::abc80(machine_config &config) +{ + abc80_state::abc80_common(config); + + // video hardware + abc80_video(config); +} + + +//------------------------------------------------- +// machine_config( tkn80 ) +//------------------------------------------------- + +void tkn80_state::tkn80(machine_config &config) +{ + abc80_state::abc80_common(config); + + // basic machine hardware + m_maincpu->set_addrmap(AS_IO, &tkn80_state::tkn80_io); + + // video hardware + tkn80_video(config); +} + //************************************************************************** @@ -567,15 +788,20 @@ ROM_START( abc80 ) ROM_REGION( 0x4000, Z80_TAG, 0 ) ROM_DEFAULT_BIOS("9913") ROM_SYSTEM_BIOS( 0, "11273", "Checksum 11273" ) - ROMX_LOAD( "3506_3.a5", 0x0000, 0x1000, CRC(7c004fb6) SHA1(9aee1d085122f4537c3e6ecdab9d799bd429ef52), ROM_BIOS(0) ) - ROMX_LOAD( "3507_3.a3", 0x1000, 0x1000, CRC(d1850a84) SHA1(f7719f3af9173601a2aa23ae38ae00de1a387ad8), ROM_BIOS(0) ) - ROMX_LOAD( "3508_3.a4", 0x2000, 0x1000, CRC(b55528e9) SHA1(3e5017e8cacad1f13215242f1bbd89d1d3eee131), ROM_BIOS(0) ) - ROMX_LOAD( "3509_3.a2", 0x3000, 0x1000, CRC(659cab1e) SHA1(181db748cef22cdcccd311a60aa6189c85343db7), ROM_BIOS(0) ) - ROM_SYSTEM_BIOS( 1, "9913", "Checksum 9913" ) - ROMX_LOAD( "3506_3_v2.a5", 0x0000, 0x1000, CRC(e2afbf48) SHA1(9883396edd334835a844dcaa792d29599a8c67b9), ROM_BIOS(1) ) - ROMX_LOAD( "3507_3_v2.a3", 0x1000, 0x1000, CRC(d224412a) SHA1(30968054bba7c2aecb4d54864b75a446c1b8fdb1), ROM_BIOS(1) ) - ROMX_LOAD( "3508_3_v2.a4", 0x2000, 0x1000, CRC(1502ba5b) SHA1(5df45909c2c4296e5701c6c99dfaa9b10b3a729b), ROM_BIOS(1) ) - ROMX_LOAD( "3509_3_v2.a2", 0x3000, 0x1000, CRC(bc8860b7) SHA1(28b6cf7f5a4f81e017c2af091c3719657f981710), ROM_BIOS(1) ) + ROMX_LOAD( "za3506_11273.a5", 0x0000, 0x1000, CRC(7c004fb6) SHA1(9aee1d085122f4537c3e6ecdab9d799bd429ef52), ROM_BIOS(0) ) + ROMX_LOAD( "za3507_11273.a3", 0x1000, 0x1000, CRC(d1850a84) SHA1(f7719f3af9173601a2aa23ae38ae00de1a387ad8), ROM_BIOS(0) ) + ROMX_LOAD( "za3508_11273.a4", 0x2000, 0x1000, CRC(b55528e9) SHA1(3e5017e8cacad1f13215242f1bbd89d1d3eee131), ROM_BIOS(0) ) + ROMX_LOAD( "za3509_11273.a2", 0x3000, 0x1000, CRC(659cab1e) SHA1(181db748cef22cdcccd311a60aa6189c85343db7), ROM_BIOS(0) ) + ROM_SYSTEM_BIOS( 1, "10042", "Checksum 10042" ) + ROMX_LOAD( "za3506_9913.a5", 0x0000, 0x1000, CRC(e2afbf48) SHA1(9883396edd334835a844dcaa792d29599a8c67b9), ROM_BIOS(1) ) + ROMX_LOAD( "za3507_9913.a3", 0x1000, 0x1000, CRC(d224412a) SHA1(30968054bba7c2aecb4d54864b75a446c1b8fdb1), ROM_BIOS(1) ) + ROMX_LOAD( "za3508_9913.a4", 0x2000, 0x1000, CRC(1502ba5b) SHA1(5df45909c2c4296e5701c6c99dfaa9b10b3a729b), ROM_BIOS(1) ) + ROMX_LOAD( "za3509_10042.a2", 0x3000, 0x1000, CRC(346f0cdb) SHA1(4262137cff9dfc82c5bd5727994ed5f9b7d22395), ROM_BIOS(1) ) + ROM_SYSTEM_BIOS( 2, "9913", "Checksum 9913" ) + ROMX_LOAD( "za3506_9913.a5", 0x0000, 0x1000, CRC(e2afbf48) SHA1(9883396edd334835a844dcaa792d29599a8c67b9), ROM_BIOS(2) ) + ROMX_LOAD( "za3507_9913.a3", 0x1000, 0x1000, CRC(d224412a) SHA1(30968054bba7c2aecb4d54864b75a446c1b8fdb1), ROM_BIOS(2) ) + ROMX_LOAD( "za3508_9913.a4", 0x2000, 0x1000, CRC(1502ba5b) SHA1(5df45909c2c4296e5701c6c99dfaa9b10b3a729b), ROM_BIOS(2) ) + ROMX_LOAD( "za3509_9913.a2", 0x3000, 0x1000, CRC(bc8860b7) SHA1(28b6cf7f5a4f81e017c2af091c3719657f981710), ROM_BIOS(2) ) ROM_REGION( 0x100, "hsync", 0 ) ROM_LOAD( "abc80_11.k5", 0x0000, 0x0100, CRC(e4f7e018) SHA1(63e718a39537f37286ea183e6469808c271dbfa5) ) // "64 40029-01" 82S129 256x4 horizontal sync @@ -599,12 +825,26 @@ ROM_END //------------------------------------------------- ROM_START( tkn80 ) - ROM_REGION( 0x5000, Z80_TAG, 0 ) - ROM_LOAD( "3506_3_v2.a5", 0x0000, 0x1000, CRC(e2afbf48) SHA1(9883396edd334835a844dcaa792d29599a8c67b9) ) - ROM_LOAD( "3507_3_v2.a3", 0x1000, 0x1000, CRC(d224412a) SHA1(30968054bba7c2aecb4d54864b75a446c1b8fdb1) ) - ROM_LOAD( "3508_3_v2.a4", 0x2000, 0x1000, CRC(1502ba5b) SHA1(5df45909c2c4296e5701c6c99dfaa9b10b3a729b) ) - ROM_LOAD( "3509_3_v2.a2", 0x3000, 0x1000, CRC(bc8860b7) SHA1(28b6cf7f5a4f81e017c2af091c3719657f981710) ) - ROM_LOAD( "tkn80-iii", 0x4000, 0x1000, CRC(f0d2e4fa) SHA1(b0263c65db39667a6fe62e61f73fe591ea10f14b) ) + ROM_REGION( 0x4000, Z80_TAG, 0 ) + ROM_DEFAULT_BIOS("9913") + ROM_SYSTEM_BIOS( 0, "11273", "Checksum 11273" ) + ROMX_LOAD( "za3506_11273.a5", 0x0000, 0x1000, CRC(7c004fb6) SHA1(9aee1d085122f4537c3e6ecdab9d799bd429ef52), ROM_BIOS(0) ) + ROMX_LOAD( "za3507_11273.a3", 0x1000, 0x1000, CRC(d1850a84) SHA1(f7719f3af9173601a2aa23ae38ae00de1a387ad8), ROM_BIOS(0) ) + ROMX_LOAD( "za3508_11273.a4", 0x2000, 0x1000, CRC(b55528e9) SHA1(3e5017e8cacad1f13215242f1bbd89d1d3eee131), ROM_BIOS(0) ) + ROMX_LOAD( "za3509_11273.a2", 0x3000, 0x1000, CRC(659cab1e) SHA1(181db748cef22cdcccd311a60aa6189c85343db7), ROM_BIOS(0) ) + ROM_SYSTEM_BIOS( 1, "10042", "Checksum 10042" ) + ROMX_LOAD( "za3506_9913.a5", 0x0000, 0x1000, CRC(e2afbf48) SHA1(9883396edd334835a844dcaa792d29599a8c67b9), ROM_BIOS(1) ) + ROMX_LOAD( "za3507_9913.a3", 0x1000, 0x1000, CRC(d224412a) SHA1(30968054bba7c2aecb4d54864b75a446c1b8fdb1), ROM_BIOS(1) ) + ROMX_LOAD( "za3508_9913.a4", 0x2000, 0x1000, CRC(1502ba5b) SHA1(5df45909c2c4296e5701c6c99dfaa9b10b3a729b), ROM_BIOS(1) ) + ROMX_LOAD( "za3509_10042.a2", 0x3000, 0x1000, CRC(346f0cdb) SHA1(4262137cff9dfc82c5bd5727994ed5f9b7d22395), ROM_BIOS(1) ) + ROM_SYSTEM_BIOS( 2, "9913", "Checksum 9913" ) + ROMX_LOAD( "za3506_9913.a5", 0x0000, 0x1000, CRC(e2afbf48) SHA1(9883396edd334835a844dcaa792d29599a8c67b9), ROM_BIOS(2) ) + ROMX_LOAD( "za3507_9913.a3", 0x1000, 0x1000, CRC(d224412a) SHA1(30968054bba7c2aecb4d54864b75a446c1b8fdb1), ROM_BIOS(2) ) + ROMX_LOAD( "za3508_9913.a4", 0x2000, 0x1000, CRC(1502ba5b) SHA1(5df45909c2c4296e5701c6c99dfaa9b10b3a729b), ROM_BIOS(2) ) + ROMX_LOAD( "za3509_9913.a2", 0x3000, 0x1000, CRC(bc8860b7) SHA1(28b6cf7f5a4f81e017c2af091c3719657f981710), ROM_BIOS(2) ) + + ROM_REGION( 0x1000, "tkn80", 0 ) + ROM_LOAD( "tkn80-iii.e", 0x0000, 0x1000, CRC(f0d2e4fa) SHA1(b0263c65db39667a6fe62e61f73fe591ea10f14b) ) ROM_REGION( 0x100, "hsync", 0 ) ROM_LOAD( "abc80_11.k5", 0x0000, 0x0100, CRC(e4f7e018) SHA1(63e718a39537f37286ea183e6469808c271dbfa5) ) // "64 40029-01" 82S129 256x4 horizontal sync @@ -630,4 +870,4 @@ ROM_END // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS COMP( 1978, abc80, 0, 0, abc80, 0, abc80_state, empty_init, "Luxor Datorer AB", "ABC 80", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND ) -COMP( 198?, tkn80, abc80, 0, abc80, 0, abc80_state, empty_init, "MYAB", "ABC 80 with TKN80", MACHINE_NOT_WORKING ) +COMP( 198?, tkn80, abc80, 0, tkn80, tkn80, tkn80_state, empty_init, "MYAB", "ABC 80 with TKN80", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND ) diff --git a/src/mame/luxor/abc80.h b/src/mame/luxor/abc80.h index 49398e0566b..48c3ead8024 100644 --- a/src/mame/luxor/abc80.h +++ b/src/mame/luxor/abc80.h @@ -92,6 +92,7 @@ public: m_tape_in_latch(1) { } + void abc80_common(machine_config &config); void abc80(machine_config &config); void abc80_video(machine_config &config); @@ -113,10 +114,13 @@ protected: u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - void draw_scanline(bitmap_rgb32 &bitmap, int y); + virtual void draw_scanline(bitmap_rgb32 &bitmap, int y); + void draw_character(bitmap_rgb32 &bitmap, int y, int sx, int hsync_data, int dv); + virtual offs_t get_videoram_addr(); + virtual u8 read_videoram(offs_t offset); - u8 read(offs_t offset); - void write(offs_t offset, u8 data); + virtual u8 read(offs_t offset); + virtual void write(offs_t offset, u8 data); DECLARE_WRITE_LINE_MEMBER( vco_voltage_w ); @@ -191,4 +195,50 @@ protected: emu_timer *m_keyboard_clear_timer = nullptr; }; + +// ======================> tkn80_state + +class tkn80_state : public abc80_state +{ +public: + tkn80_state(const machine_config &mconfig, device_type type, const char *tag) : + abc80_state(mconfig, type, tag), + m_rom_e(*this, "tkn80"), + m_char_ram(*this, "char_ram", 0x800, ENDIANNESS_LITTLE), + m_config(*this, "CONFIG"), + m_80(true) + { } + + void tkn80(machine_config &config); + void tkn80_video(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + virtual void video_reset() override; + + virtual void draw_scanline(bitmap_rgb32 &bitmap, int y) override; + virtual offs_t get_videoram_addr() override; + virtual u8 read_videoram(offs_t offset) override; + + void set_screen_params(void); + + virtual u8 read(offs_t offset) override; + virtual void write(offs_t offset, u8 data) override; + + uint8_t in3_r(); + uint8_t in4_r(); + + void tkn80_io(address_map &map); + + required_memory_region m_rom_e; + memory_share_creator m_char_ram; + required_ioport m_config; + + bool m_80; + offs_t m_rom_offset; +}; + + + #endif // MAME_LUXOR_ABC80_H diff --git a/src/mame/luxor/abc80_v.cpp b/src/mame/luxor/abc80_v.cpp index 1c3ad19829d..3bbd913e72d 100644 --- a/src/mame/luxor/abc80_v.cpp +++ b/src/mame/luxor/abc80_v.cpp @@ -10,10 +10,47 @@ #include "abc80.h" #include "screen.h" +void tkn80_state::set_screen_params(void) +{ + if (m_80) + { + m_screen->set_raw(XTAL(11'980'800), ABC80_HTOTAL*2, ABC80_HBEND*2, ABC80_HBSTART*2, ABC80_VTOTAL, ABC80_VBEND, ABC80_VBSTART); + m_scanline_timer->adjust(m_screen->time_until_pos(0, ABC80_HBEND*2), 0, m_screen->scan_period()); + } + else + { + m_screen->set_raw(XTAL(11'980'800)/2, ABC80_HTOTAL, ABC80_HBEND, ABC80_HBSTART, ABC80_VTOTAL, ABC80_VBEND, ABC80_VBSTART); + m_scanline_timer->adjust(m_screen->time_until_pos(0, ABC80_HBEND), 0, m_screen->scan_period()); + } +} + +uint8_t tkn80_state::in3_r() +{ + if (!machine().side_effects_disabled() && m_80) + { + m_80 = false; + + set_screen_params(); + } + + return 0xff; +}; + +uint8_t tkn80_state::in4_r() +{ + if (!machine().side_effects_disabled() && !m_80) + { + m_80 = true; + + set_screen_params(); + } + + return 0xff; +}; + void abc80_state::draw_scanline(bitmap_rgb32 &bitmap, int y) { uint8_t vsync_data = m_vsync_prom->base()[y]; - uint8_t l = m_line_prom->base()[y]; int dv = (vsync_data & ABC80_K2_DV) ? 1 : 0; if (!(vsync_data & ABC80_K2_FRAME_RESET)) @@ -25,8 +62,6 @@ void abc80_state::draw_scanline(bitmap_rgb32 &bitmap, int y) for (int sx = 0; sx < 64; sx++) { uint8_t hsync_data = m_hsync_prom->base()[sx]; - int dh = (hsync_data & ABC80_K5_DH) ? 1 : 0; - uint8_t data = 0; if (hsync_data & ABC80_K5_LINE_END) { @@ -37,78 +72,55 @@ void abc80_state::draw_scanline(bitmap_rgb32 &bitmap, int y) m_mode = 0; } - /* - - Video RAM Addressing Scheme - - A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 - R2 R1 R0 xx xx xx xx C2 C1 C0 + draw_character(bitmap, y, sx, dv, hsync_data); - A6 A5 A4 A3 = 00 C5 C4 C3 + R4 R3 R4 R3 - - */ - - int a = (m_c >> 3) & 0x07; - int b = ((m_r >> 1) & 0x0c) | ((m_r >> 3) & 0x03); - int s = (a + b) & 0x0f; - uint16_t videoram_addr = ((m_r & 0x07) << 7) | (s << 3) | (m_c & 0x07); - uint8_t videoram_data = m_latch; - uint8_t attr_addr = ((dh & dv) << 7) | (videoram_data & 0x7f); - uint8_t attr_data = m_attr_prom->base()[attr_addr]; - - int blank = (attr_data & ABC80_J3_BLANK) ? 1 : 0; - int j = (attr_data & ABC80_J3_TEXT) ? 1 : 0; - int k = (attr_data & ABC80_J3_GRAPHICS) ? 1 : 0; - int versal = (attr_data & ABC80_J3_VERSAL) ? 1 : 0; - int cursor = (videoram_data & ABC80_CHAR_CURSOR) ? 1 : 0; - - if (!j && k) m_mode = 0; - if (j && !k) m_mode = 1; - if (j && k) m_mode = !m_mode; - - if (m_mode & versal) + if (hsync_data & ABC80_K5_ROW_START) { - // graphics mode - int r0 = 1, r1 = 1, r2 = 1; - - if (l < 3) r0 = 0; else if (l < 7) r1 = 0; else r2 = 0; + // clock F4 + m_c++; + } + } - int c0 = BIT(videoram_data, 0) || r0; - int c1 = BIT(videoram_data, 1) || r0; - int c2 = BIT(videoram_data, 2) || r1; - int c3 = BIT(videoram_data, 3) || r1; - int c4 = BIT(videoram_data, 4) || r2; - int c5 = BIT(videoram_data, 6) || r2; + if (vsync_data & ABC80_K2_FRAME_END) + { + // clock F2 + m_r++; + } +} - if (c0 && c2 && c4) data |= 0xe0; - if (c1 && c3 && c5) data |= 0x1c; - } - else - { - // text mode - data = m_rocg->read(videoram_data & 0x7f, l); - } +void tkn80_state::draw_scanline(bitmap_rgb32 &bitmap, int y) +{ + uint8_t vsync_data = m_vsync_prom->base()[y]; + int dv = (vsync_data & ABC80_K2_DV) ? 1 : 0; - // shift out pixels - for (int bit = 0; bit < 6; bit++) - { - int color = BIT(data, 7); - int x = (sx * 6) + bit; + if (!(vsync_data & ABC80_K2_FRAME_RESET)) + { + // reset F2 + m_r = 0; + } - color ^= (cursor & m_blink); - color &= blank; + int cols = m_80 ? 128 : 64; + for (int sx = 0; sx < cols; sx++) + { + uint8_t hsync_data = m_hsync_prom->base()[m_80 ? (sx / 2) : sx]; - bitmap.pix(y, x) = m_palette->pen(color); + if (hsync_data & ABC80_K5_LINE_END) + { + // reset F4 + m_c = 0; - data <<= 1; + // reset J5 + m_mode = 0; } - m_latch = m_video_ram[videoram_addr]; + draw_character(bitmap, y, sx, dv, hsync_data); if (hsync_data & ABC80_K5_ROW_START) { - // clock F4 - m_c++; + if (!m_80 || sx > 30) { + // clock F4 + m_c++; + } } } @@ -119,6 +131,139 @@ void abc80_state::draw_scanline(bitmap_rgb32 &bitmap, int y) } } +void abc80_state::draw_character(bitmap_rgb32 &bitmap, int y, int sx, int dv, int hsync_data) +{ + uint8_t l = m_line_prom->base()[y]; + int dh = (hsync_data & ABC80_K5_DH) ? 1 : 0; + uint8_t data = 0; + + uint16_t videoram_addr = get_videoram_addr(); + uint8_t videoram_data = m_latch; + uint8_t attr_addr = ((dh & dv) << 7) | (videoram_data & 0x7f); + uint8_t attr_data = m_attr_prom->base()[attr_addr]; + + int blank = (attr_data & ABC80_J3_BLANK) ? 1 : 0; + int j = (attr_data & ABC80_J3_TEXT) ? 1 : 0; + int k = (attr_data & ABC80_J3_GRAPHICS) ? 1 : 0; + int versal = (attr_data & ABC80_J3_VERSAL) ? 1 : 0; + int cursor = (videoram_data & ABC80_CHAR_CURSOR) ? 1 : 0; + + if (!j && k) m_mode = 0; + if (j && !k) m_mode = 1; + if (j && k) m_mode = !m_mode; + + if (m_mode & versal) + { + // graphics mode + int r0 = 1, r1 = 1, r2 = 1; + + if (l < 3) r0 = 0; else if (l < 7) r1 = 0; else r2 = 0; + + int c0 = BIT(videoram_data, 0) || r0; + int c1 = BIT(videoram_data, 1) || r0; + int c2 = BIT(videoram_data, 2) || r1; + int c3 = BIT(videoram_data, 3) || r1; + int c4 = BIT(videoram_data, 4) || r2; + int c5 = BIT(videoram_data, 6) || r2; + + if (c0 && c2 && c4) data |= 0xe0; + if (c1 && c3 && c5) data |= 0x1c; + } + else + { + // text mode + data = m_rocg->read(videoram_data & 0x7f, l); + } + + // shift out pixels + for (int bit = 0; bit < 6; bit++) + { + int color = BIT(data, 7); + int x = (sx * 6) + bit; + + color ^= (cursor & m_blink); + color &= blank; + + bitmap.pix(y, x) = m_palette->pen(color); + + data <<= 1; + } + + m_latch = read_videoram(videoram_addr); +} + +offs_t abc80_state::get_videoram_addr() +{ + /* + + Video RAM Addressing Scheme + + A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 + R2 R1 R0 xx xx xx xx C2 C1 C0 + + A6 A5 A4 A3 = 00 C5 C4 C3 + R4 R3 R4 R3 + + */ + + int a = (m_c >> 3) & 0x07; + int b = ((m_r >> 1) & 0x0c) | ((m_r >> 3) & 0x03); + int s = (a + b) & 0x0f; + + return ((m_r & 0x07) << 7) | (s << 3) | (m_c & 0x07); +} + +offs_t tkn80_state::get_videoram_addr() +{ + if (m_80) + { + /* + + Video RAM Addressing Scheme + + A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 + R2 R1 R0 xx xx xx xx C3 C2 C1 C0 + + A7 A6 A5 A4 = 00 C6 C5 C4 + R4 R3 R4 R3 + + */ + + int a = (m_c >> 4) & 0x07; + int b = ((m_r >> 1) & 0x0c) | ((m_r >> 3) & 0x03); + int s = (a + b) & 0x1f; + + return ((m_r & 0x07) << 8) | (s << 4) | (m_c & 0x0f); + } + else + { + /* + + Video RAM Addressing Scheme + + A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0 + 1 R2 R1 R0 xx xx xx xx C2 C1 C0 + + A6 A5 A4 A3 = 00 C5 C4 C3 + R4 R3 R4 R3 + + */ + + int a = (m_c >> 3) & 0x07; + int b = ((m_r >> 1) & 0x0c) | ((m_r >> 3) & 0x03); + int s = (a + b) & 0x0f; + + return 0x400 | ((m_r & 0x07) << 7) | (s << 3) | (m_c & 0x07); + } +} + +u8 abc80_state::read_videoram(offs_t offset) +{ + return m_video_ram[offset]; +} + +u8 tkn80_state::read_videoram(offs_t offset) +{ + return m_char_ram[offset]; +} + //------------------------------------------------- // video_start - @@ -143,6 +288,22 @@ void abc80_state::video_start() } +//------------------------------------------------- +// video_reset - +//------------------------------------------------- + +void tkn80_state::video_reset() +{ + u8 config = m_config->read(); + + m_80 = BIT(config, 0); + set_screen_params(); + + m_blink = 1; + m_blink_timer->enable(BIT(config, 1)); +} + + //------------------------------------------------- // screen_update - //------------------------------------------------- @@ -170,3 +331,20 @@ void abc80_state::abc80_video(machine_config &config) SN74S263(config, m_rocg, 0); m_rocg->set_palette(m_palette); } + + +//------------------------------------------------- +// machine_config( tkn80_video ) +//------------------------------------------------- + +void tkn80_state::tkn80_video(machine_config &config) +{ + PALETTE(config, m_palette, palette_device::MONOCHROME); + + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_screen_update(FUNC(tkn80_state::screen_update)); + m_screen->set_raw(XTAL(11'980'800), ABC80_HTOTAL*2, ABC80_HBEND*2, ABC80_HBSTART*2, ABC80_VTOTAL, ABC80_VBEND, ABC80_VBSTART); + + SN74S263(config, m_rocg, 0); + m_rocg->set_palette(m_palette); +} -- cgit v1.2.3