summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/ti99/internal/998board.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/ti99/internal/998board.h')
-rw-r--r--src/devices/bus/ti99/internal/998board.h562
1 files changed, 562 insertions, 0 deletions
diff --git a/src/devices/bus/ti99/internal/998board.h b/src/devices/bus/ti99/internal/998board.h
new file mode 100644
index 00000000000..d89e0a736e8
--- /dev/null
+++ b/src/devices/bus/ti99/internal/998board.h
@@ -0,0 +1,562 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ TI-99/8 main board logic
+
+ This component implements the address decoder and mapper logic from the
+ TI-99/8 console.
+
+ See 998board.c for documentation
+
+ Michael Zapf
+
+*****************************************************************************/
+
+#ifndef MAME_BUS_TI99_INTERNAL_998BOARD_H
+#define MAME_BUS_TI99_INTERNAL_998BOARD_H
+
+#pragma once
+
+#include "bus/ti99/ti99defs.h"
+#include "gromport.h"
+
+#include "bus/ti99/peb/peribox.h"
+#include "machine/ram.h"
+#include "machine/tmc0430.h"
+#include "sound/sn76496.h"
+#include "sound/tms5220.h"
+#include "video/tms9928a.h"
+
+namespace bus { namespace ti99 { namespace internal {
+
+#define VAQUERRO_TAG "vaquerro"
+#define MOFETTA_TAG "mofetta"
+#define AMIGO_TAG "amigo"
+#define OSO_TAG "oso"
+
+class mainboard8_device;
+
+/*
+ Custom chip: Vaquerro
+*/
+class vaquerro_device : public device_t
+{
+public:
+ vaquerro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void device_start() override;
+ void device_reset() override;
+
+ line_state ready();
+ void treset();
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_SETADDRESS_DBIN_MEMBER( set_address );
+
+ DECLARE_READ_LINE_MEMBER( sprd_out );
+ DECLARE_READ_LINE_MEMBER( spwt_out );
+ DECLARE_READ_LINE_MEMBER( sccs_out );
+ DECLARE_READ_LINE_MEMBER( sromcs_out );
+
+ // Collective select line query
+ int gromcs_out();
+
+ DECLARE_READ_LINE_MEMBER( vdprd_out );
+ DECLARE_READ_LINE_MEMBER( vdpwt_out );
+ DECLARE_READ_LINE_MEMBER( lascsq_out );
+ DECLARE_READ_LINE_MEMBER( ggrdy_out );
+ DECLARE_WRITE_LINE_MEMBER( hold_cpu );
+
+ DECLARE_WRITE_LINE_MEMBER( crus_in );
+ DECLARE_WRITE_LINE_MEMBER( crusgl_in );
+ DECLARE_WRITE_LINE_MEMBER( clock_in );
+ DECLARE_WRITE_LINE_MEMBER( memen_in );
+
+ DECLARE_WRITE_LINE_MEMBER( sgmry );
+ DECLARE_WRITE_LINE_MEMBER( tsgry );
+ DECLARE_WRITE_LINE_MEMBER( p8gry );
+ DECLARE_WRITE_LINE_MEMBER( p3gry );
+
+private:
+ /*
+ Wait state generator (part of Vaquerro)
+ */
+ class waitstate_generator
+ {
+ public:
+ waitstate_generator() :
+ m_counting(false),
+ m_generate(false),
+ m_counter(0),
+ m_addressed(true),
+ m_ready(true)
+ {
+ }
+
+ virtual ~waitstate_generator() { }
+ void select_in(bool addressed);
+ virtual void ready_in(line_state ready) = 0;
+ virtual void clock_in(line_state clkout) = 0;
+ void treset_in(line_state reset);
+
+ int select_out();
+ void init(int select_value) { m_selvalue = select_value; }
+
+ line_state ready_out();
+
+ bool is_counting();
+ bool is_generating();
+ bool is_ready();
+
+ protected:
+ // Two flipflops
+ bool m_counting;
+ bool m_generate;
+ // Counter
+ int m_counter;
+
+ // Select value (indicates selected line)
+ int m_selvalue;
+
+ // Line state flags
+ bool m_addressed;
+ bool m_ready;
+ };
+
+ class grom_waitstate_generator : public waitstate_generator
+ {
+ public:
+ void ready_in(line_state ready) override;
+ void clock_in(line_state clkout) override;
+ };
+
+ class video_waitstate_generator : public waitstate_generator
+ {
+ public:
+ void ready_in(line_state ready) override { }
+ void clock_in(line_state clkout) override;
+ };
+
+ // Memory cycle state
+ bool m_memen;
+
+ // Waiting for video
+ bool m_video_wait;
+
+ // State of the CRUS line
+ int m_crus;
+
+ // Are the GROM libraries turned on?
+ bool m_crugl;
+
+ // Do we have a logical address space match?
+ bool m_lasreq = false;
+
+ // Keep the decoding result (opens the SRY gate)
+ bool m_grom_or_video = false;
+
+ // Select lines
+ bool m_spwt;
+ bool m_sccs;
+ bool m_sromcs;
+ bool m_sprd;
+ bool m_vdprd;
+ bool m_vdpwt;
+
+ // Collective GROM select state
+ int m_gromsel;
+
+ // Outgoing READY
+ int m_ggrdy;
+
+ // Outgoing READY latch (common flipflop driving SRY)
+ bool m_sry;
+
+ // Holds the A14 address line state. We need this for the clock_in method.
+ int m_a14;
+
+ // Keeps the recent DBIN level
+ int m_dbin_level;
+
+ // Wait state logic components
+ grom_waitstate_generator m_sgmws, m_tsgws, m_p8gws, m_p3gws;
+ video_waitstate_generator m_vidws;
+
+ // Pointer to mainboard
+ mainboard8_device* m_mainboard;
+};
+
+/*
+ Custom chip: Mofetta
+*/
+class mofetta_device : public device_t
+{
+public:
+ mofetta_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void device_start() override;
+ void device_reset() override;
+
+ DECLARE_WRITE8_MEMBER( cruwrite );
+ DECLARE_SETADDRESS_DBIN_MEMBER( set_address );
+
+ // Debugger support
+ bool hexbus_access_debug();
+ bool intdsr_access_debug();
+
+ DECLARE_WRITE_LINE_MEMBER( clock_in );
+ DECLARE_WRITE_LINE_MEMBER( msast_in );
+ DECLARE_WRITE_LINE_MEMBER( lascs_in );
+ DECLARE_WRITE_LINE_MEMBER( pmemen_in );
+ DECLARE_WRITE_LINE_MEMBER( skdrcs_in );
+
+ DECLARE_READ8_MEMBER( rom1cs_out );
+ DECLARE_READ_LINE_MEMBER( gromclk_out );
+
+ DECLARE_READ_LINE_MEMBER( alccs_out );
+ DECLARE_READ_LINE_MEMBER( prcs_out );
+ DECLARE_READ_LINE_MEMBER( cmas_out );
+ DECLARE_READ_LINE_MEMBER( dbc_out );
+
+ DECLARE_READ_LINE_MEMBER( rom1cs_out );
+ DECLARE_READ_LINE_MEMBER( rom1am_out );
+ DECLARE_READ_LINE_MEMBER( rom1al_out );
+
+private:
+ // Memory cycle state
+ bool m_pmemen;
+
+ // Logical access
+ bool m_lasreq;
+
+ // DRAM access
+ bool m_skdrcs;
+
+ // Indicates the UP level of the GROMCLK
+ bool m_gromclk_up;
+
+ // Have we got the upper word of the address?
+ bool m_gotfirstword;
+
+ // Address latch
+ int m_address_latch;
+
+ // Most significant byte of the 24-bit address
+ int m_prefix;
+
+ // CRU select of the 1700 device
+ bool m_alcpg;
+
+ // CRU select of the 2700 device
+ bool m_txspg;
+
+ // ROM1 select lines
+ bool m_rom1cs;
+ bool m_rom1am;
+ bool m_rom1al;
+
+ // OSO select
+ bool m_alccs;
+
+ // Pascal ROM select line
+ bool m_prcs;
+
+ // Cartridge port select line
+ bool m_cmas;
+
+ // GROM clock count (as frequency divider)
+ int m_gromclock_count;
+
+ // Remember last msast state for edge detection
+ int m_msast;
+
+ // Pointer to mainboard
+ mainboard8_device* m_mainboard;
+};
+
+/*
+ Custom chip: Amigo
+*/
+class amigo_device : public device_t
+{
+public:
+ amigo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void device_start() override;
+ void device_reset() override;
+
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+ DECLARE_SETOFFSET_MEMBER( set_address );
+
+ // Debugger support
+ int get_physical_address_debug(offs_t offset);
+ void mapper_access_debug(int data);
+
+ DECLARE_WRITE_LINE_MEMBER( srdy_in );
+ DECLARE_WRITE_LINE_MEMBER( clock_in );
+ DECLARE_WRITE_LINE_MEMBER( crus_in );
+ DECLARE_WRITE_LINE_MEMBER( lascs_in );
+ DECLARE_WRITE_LINE_MEMBER( memen_in );
+
+ DECLARE_WRITE_LINE_MEMBER( holda_in );
+
+ DECLARE_READ_LINE_MEMBER( cpury_out );
+ DECLARE_READ_LINE_MEMBER( sramcs_out );
+ DECLARE_READ_LINE_MEMBER( skdrcs_out );
+
+ void connect_sram(uint8_t* sram) { m_sram = sram; }
+ bool mapper_accessed() { return m_mapper_accessed; }
+
+private:
+ // Memory cycle state
+ bool m_memen;
+
+ // DMA methods for loading/saving maps
+ void mapper_load();
+ void mapper_save();
+
+ // Address mapper registers. Each offset is selected by the first 4 bits
+ // of the logical address.
+ uint32_t m_base_register[16];
+
+ // Indicates a logical space access
+ bool m_logical_space;
+
+ // Physical address
+ uint32_t m_physical_address;
+
+ // Pointer to SRAM where AMIGO needs to upload/download its map values
+ uint8_t* m_sram;
+
+ // Pointer to mainboard
+ mainboard8_device* m_mainboard;
+
+ // Keep the system ready state
+ int m_srdy;
+
+ // Outgoing READY level
+ int m_ready_out;
+
+ // Keep the CRUS setting
+ int m_crus;
+
+ // State of the address creation
+ int m_amstate;
+
+ // Protection flags
+ int m_protflag;
+
+ // Accessing SRAM
+ bool m_sram_accessed;
+
+ // Accessing DRAM
+ bool m_dram_accessed;
+
+ // Accessing the mapper
+ bool m_mapper_accessed;
+
+ // HOLDA flag
+ bool m_hold_acknowledged;
+
+ // Address in SRAM during DMA
+ uint32_t m_sram_address;
+
+ // Number of the currently loaded/save base register
+ int m_basereg;
+
+ // Latched value for mapper DMA transfer
+ uint32_t m_mapvalue;
+};
+
+/*
+ Custom chip: OSO
+*/
+class oso_device : public device_t
+{
+public:
+ oso_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+ void device_start() override;
+
+private:
+ uint8_t m_data;
+ uint8_t m_status;
+ uint8_t m_control;
+ uint8_t m_xmit;
+};
+
+class mainboard8_device : public device_t
+{
+public:
+ mainboard8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // Memory space
+ DECLARE_READ8_MEMBER( read );
+ DECLARE_WRITE8_MEMBER( write );
+ DECLARE_SETOFFSET_MEMBER( setoffset );
+
+ // Memory space for debugger access
+ DECLARE_READ8_MEMBER( debugger_read );
+ DECLARE_WRITE8_MEMBER( debugger_write );
+
+ // I/O space
+ DECLARE_READ8Z_MEMBER( crureadz );
+ DECLARE_WRITE8_MEMBER( cruwrite );
+
+ // Control lines
+ DECLARE_WRITE_LINE_MEMBER( clock_in );
+ DECLARE_WRITE_LINE_MEMBER( dbin_in );
+ DECLARE_WRITE_LINE_MEMBER( msast_in );
+ DECLARE_WRITE_LINE_MEMBER( crus_in );
+ DECLARE_WRITE_LINE_MEMBER( ptgen_in );
+ DECLARE_WRITE_LINE_MEMBER( reset_console );
+ DECLARE_WRITE_LINE_MEMBER( hold_cpu );
+ DECLARE_WRITE_LINE_MEMBER( ggrdy_in );
+
+ DECLARE_WRITE_LINE_MEMBER( holda_line );
+
+ template<class _Object> static devcb_base &set_ready_wr_callback(device_t &device, _Object object)
+ {
+ return downcast<mainboard8_device &>(device).m_ready.set_callback(object);
+ }
+
+ template<class _Object> static devcb_base &set_reset_wr_callback(device_t &device, _Object object)
+ {
+ return downcast<mainboard8_device &>(device).m_console_reset.set_callback(object);
+ }
+
+ template<class _Object> static devcb_base &set_hold_wr_callback(device_t &device, _Object object)
+ {
+ return downcast<mainboard8_device &>(device).m_hold_line.set_callback(object);
+ }
+
+ void set_paddress(int address);
+
+ // Ready lines from GROMs
+ DECLARE_WRITE_LINE_MEMBER( system_grom_ready );
+ DECLARE_WRITE_LINE_MEMBER( ptts_grom_ready );
+ DECLARE_WRITE_LINE_MEMBER( p8_grom_ready );
+ DECLARE_WRITE_LINE_MEMBER( p3_grom_ready );
+ DECLARE_WRITE_LINE_MEMBER( sound_ready );
+ DECLARE_WRITE_LINE_MEMBER( speech_ready );
+ DECLARE_WRITE_LINE_MEMBER( pbox_ready );
+
+ // Emulation
+ // void set_gromport(gromport_device* dev) { m_gromport = dev; }
+
+protected:
+ void device_start() override;
+ void device_reset() override;
+ machine_config_constructor device_mconfig_additions() const override;
+
+private:
+ // Holds the state of the A14 line
+ bool m_A14_set;
+
+ // Propagates the end of the memory cycle
+ void cycle_end();
+
+ // Original logical address.
+ int m_logical_address;
+
+ // Mapped physical address.
+ int m_physical_address;
+
+ // Hold the address space value so that we can use it in other methods.
+ address_space* m_space;
+
+ // Indicates that a byte is waiting on the data bus (see m_latched_data)
+ bool m_pending_write;
+
+ // Hold the value of the data bus. In a real machine, the data bus continues
+ // to show that value, but in this emulation we have a push mechanism.
+ uint8_t m_latched_data;
+
+ // Hold the level of the GROMCLK line
+ int m_gromclk;
+
+ // Selecting GROM libraries
+ void select_groms();
+
+ // Previous select state
+ int m_prev_grom;
+
+ // Ready states
+ bool m_speech_ready;
+ bool m_sound_ready;
+ bool m_pbox_ready;
+
+ // Keeps the recent DBIN level
+ int m_dbin_level;
+
+ // Ready line to the CPU
+ devcb_write_line m_ready;
+
+ // Reset line to the main system
+ devcb_write_line m_console_reset;
+
+ // Hold line to the main system
+ devcb_write_line m_hold_line;
+
+ // Custom chips
+ required_device<vaquerro_device> m_vaquerro;
+ required_device<mofetta_device> m_mofetta;
+ required_device<amigo_device> m_amigo;
+ required_device<oso_device> m_oso;
+
+ // More devices
+ required_device<tms9928a_device> m_video;
+ required_device<sn76496_base_device> m_sound;
+ required_device<cd2501ecd_device> m_speech;
+ required_device<gromport_device> m_gromport;
+ required_device<bus::ti99::peb::peribox_device> m_peb;
+ required_device<ram_device> m_sram;
+ required_device<ram_device> m_dram;
+
+ // Debugging
+ int m_last_ready;
+ line_state m_crus_debug;
+
+ // System GROM library
+ tmc0430_device* m_sgrom[3];
+
+ // Text-to-speech GROM library
+ tmc0430_device* m_tsgrom[8];
+
+ // Pascal 8 GROM library
+ tmc0430_device* m_p8grom[8];
+
+ // Pascal 3 GROM library
+ tmc0430_device* m_p3grom[3];
+
+ // Idle flags for GROMs
+ bool m_sgrom_idle;
+ bool m_tsgrom_idle;
+ bool m_p8grom_idle;
+ bool m_p3grom_idle;
+
+ // ROM area of the system.
+ uint8_t* m_rom0;
+ uint8_t* m_rom1;
+ uint8_t* m_pascalrom;
+};
+
+} } } // end namespace bus::ti99::internal
+
+#define MCFG_MAINBOARD8_READY_CALLBACK(_write) \
+ devcb = &bus::ti99::internal::mainboard8_device::set_ready_wr_callback(*device, DEVCB_##_write);
+
+#define MCFG_MAINBOARD8_RESET_CALLBACK(_write) \
+ devcb = &bus::ti99::internal::mainboard8_device::set_reset_wr_callback(*device, DEVCB_##_write);
+
+#define MCFG_MAINBOARD8_HOLD_CALLBACK(_write) \
+ devcb = &bus::ti99::internal::mainboard8_device::set_hold_wr_callback(*device, DEVCB_##_write);
+
+DECLARE_DEVICE_TYPE_NS(TI99_MAINBOARD8, bus::ti99::internal, mainboard8_device)
+DECLARE_DEVICE_TYPE_NS(TI99_VAQUERRO, bus::ti99::internal, vaquerro_device)
+DECLARE_DEVICE_TYPE_NS(TI99_MOFETTA, bus::ti99::internal, mofetta_device)
+DECLARE_DEVICE_TYPE_NS(TI99_AMIGO, bus::ti99::internal, amigo_device)
+DECLARE_DEVICE_TYPE_NS(TI99_OSO, bus::ti99::internal, oso_device)
+
+#endif // MAME_BUS_TI99_INTERNAL_998BOARD_H