summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/ti99/internal/992board.h
blob: 7e79c8d135821302df2034274b18039cbb828e95 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// license:LGPL-2.1+
// copyright-holders:Michael Zapf
/****************************************************************************

    TI-99/2 main board logic

    This component implements the custom video controller and interface chip
    from the TI-99/2 console.

    See 992board.cpp for documentation

    Michael Zapf

*****************************************************************************/

#ifndef MAME_BUS_TI99_INTERNAL_992BOARD_H
#define MAME_BUS_TI99_INTERNAL_992BOARD_H

#pragma once

#include "screen.h"
#include "bus/ti99/ti99defs.h"
#include "bus/hexbus/hexbus.h"
#include "imagedev/cassette.h"

namespace bus { namespace ti99 { namespace internal {

class video992_device : public device_t,
							public device_video_interface
{
public:
	// Complete line (31.848 us)
	static constexpr unsigned TOTAL_HORZ                 = 342;
	static constexpr unsigned TOTAL_VERT_NTSC            = 262;

	template <class Object> devcb_base &set_readmem_callback(Object &&cb) { return m_mem_read_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_hold_callback(Object &&cb) { return m_hold_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_int_callback(Object &&cb) { return m_int_cb.set_callback(std::forward<Object>(cb)); }

	// Delay(2) + ColorBurst(14) + Delay(8) + LeftBorder(13)
	static constexpr unsigned HORZ_DISPLAY_START         = 2 + 14 + 8 + 13;
	// RightBorder(15) + Delay(8) + HorizSync(26)
	static constexpr unsigned VERT_DISPLAY_START_NTSC    = 13 + 27;

	// update the screen
	uint32_t screen_update( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect );

	// Video enable
	DECLARE_WRITE_LINE_MEMBER( videna );

protected:
	video992_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
	int     m_beol;

private:
	static const device_timer_id HOLD_TIME = 0;
	static const device_timer_id FREE_TIME = 1;

	void device_start() override;
	void device_reset() override;
	void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
	std::string tts(attotime t);
	devcb_read8   m_mem_read_cb; // Callback to read memory
	devcb_write_line m_hold_cb;
	devcb_write_line m_int_cb;

	bitmap_rgb32 m_tmpbmp;
	emu_timer   *m_free_timer;
	emu_timer   *m_hold_timer;

	int         m_top_border;
	int         m_vertical_size;

	rgb_t       m_border_color;
	rgb_t       m_background_color;
	rgb_t       m_text_color;

	bool        m_videna;

	attotime    m_hold_time;
};

/* Variant for TI-99/2 24K */
class video992_24_device : public video992_device
{
public:
	video992_24_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

/* Variant for TI-99/2 32K */
class video992_32_device : public video992_device
{
public:
	video992_32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

/*
    I/O custom chip
*/
class io992_device : public bus::hexbus::hexbus_chained_device
{
public:
	io992_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	DECLARE_READ8_MEMBER( cruread );
	DECLARE_WRITE8_MEMBER( cruwrite );
	void device_start() override;
	template <class Object> devcb_base &set_rombank_callback(Object &&cb) { return m_set_rom_bank.set_callback(std::forward<Object>(cb)); }
	ioport_constructor device_input_ports() const override;

protected:
	io992_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
	bool m_have_banked_rom;

	void hexbus_value_changed(uint8_t data) override;

private:
	const uint8_t m_hexbval[6] = { 0x01, 0x02, 0x40, 0x80, 0x10, 0x04 };

	required_device<hexbus::hexbus_device> m_hexbus;
	required_device<cassette_image_device> m_cassette;
	required_device<video992_device> m_videoctrl;
	required_ioport_array<8> m_keyboard;

	// Set ROM bank
	devcb_write_line m_set_rom_bank;

	// Keyboard row
	int m_key_row;

	// Hexbus outgoing signal latch. Should be set to D7 when idle.
	// (see hexbus.cpp)
	uint8_t m_latch_out;

	// Hexbus incoming signal latch. Should be set to D7 when idle.
	uint8_t m_latch_in;

	// Hexbus inhibit. This prevents the incoming latches to store the data.
	bool m_communication_disable;
};


/* Variant for TI-99/2 24K */
class io992_24_device : public io992_device
{
public:
	io992_24_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

/* Variant for TI-99/2 32K */
class io992_32_device : public io992_device
{
public:
	io992_32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

} } } // end namespace bus::ti99::internal

#define MCFG_VIDEO992_SCREEN_ADD(_screen_tag) \
	MCFG_VIDEO_SET_SCREEN(_screen_tag) \
	MCFG_SCREEN_ADD( _screen_tag, RASTER ) \
	MCFG_SCREEN_RAW_PARAMS( XTAL(10'738'635) / 2, bus::ti99::internal::video992_device::TOTAL_HORZ, bus::ti99::internal::video992_device::HORZ_DISPLAY_START-12, bus::ti99::internal::video992_device::HORZ_DISPLAY_START + 256 + 12, \
			bus::ti99::internal::video992_device::TOTAL_VERT_NTSC, bus::ti99::internal::video992_device::VERT_DISPLAY_START_NTSC - 12, bus::ti99::internal::video992_device::VERT_DISPLAY_START_NTSC + 192 + 12 )

#define MCFG_VIDEO992_MEM_ACCESS_CB(_devcb) \
	downcast<bus::ti99::internal::video992_device &>(*device).set_readmem_callback(DEVCB_##_devcb);

#define MCFG_VIDEO992_HOLD_CB(_devcb) \
	downcast<bus::ti99::internal::video992_device &>(*device).set_hold_callback(DEVCB_##_devcb);

#define MCFG_VIDEO992_INT_CB(_devcb) \
	downcast<bus::ti99::internal::video992_device &>(*device).set_int_callback(DEVCB_##_devcb);

#define MCFG_SET_ROMBANK_HANDLER( _devcb ) \
	downcast<bus::ti99::internal::io992_device &>(*device).set_rombank_callback(DEVCB_##_devcb);

DECLARE_DEVICE_TYPE_NS(VIDEO99224, bus::ti99::internal, video992_24_device)
DECLARE_DEVICE_TYPE_NS(VIDEO99232, bus::ti99::internal, video992_32_device)
DECLARE_DEVICE_TYPE_NS(IO99224, bus::ti99::internal, io992_24_device)
DECLARE_DEVICE_TYPE_NS(IO99232, bus::ti99::internal, io992_32_device)

#endif // MAME_BUS_TI99_INTERNAL_992BOARD_H