1 // license:GPL-2.0+
2 // copyright-holders: Felipe Sanches
3 /***************************************************************************
4 
5     Itautec I7000
6 
7     driver by Felipe C. da S. Sanches <juca@members.fsf.org>
8     with tech info provided by Alexandre Souza (a.k.a. Tabajara).
9 
10     The portuguese Wikipedia article available at
11     http://pt.wikipedia.org/wiki/Itautec_I-7000
12     also provides a technical overview of this machine:
13 
14     The I-7000 was the first computer manufactured by Itautec
15     (http://www.itautec.com.br/pt-br/produtos). It was originally an 8 bit CP/M
16     computer that became an IBM PC-XT clone in later hardware revisions which
17     took the "I-7000 PC-XT" name.
18 
19     * Released in 1982
20     * Operating System: SIM/M / BASIC
21     * CPU: National NSC800 D-4 at 4,00 MHz
22     * Memory: 64KB to 128KB
23     * keyboards: 80 keys (with a reduced numerical keypad and function keys)
24     * display:
25      - 40 X 25 text
26      - 80 X 25 text
27      - 160 X 100 (8 colors)
28      - 640 X 200 (monochrome, with an expansion board)
29      - 320 X 200 (16 colors, with an expansion board)
30     * Expansion slots:
31      - 1 frontal cart slot
32      - 4 internal expansion slots
33     * Ports:
34      - 1 composite video output for a color monitor
35      - 2 cassette interfaces
36      - 1 RS-232C serial port
37      - 1 parallel interface
38     * Storage:
39      - Cassette recorder
40      - Up to 4 external floppy drives: 8" (FD/DD, 1,1MB) or 5" 1/4
41      - Up to 1 external 10 MB hard-drive
42 
43 ****************************************************************************/
44 
45 #include "emu.h"
46 #include "bus/generic/carts.h"
47 #include "bus/generic/slot.h"
48 #include "cpu/z80/z80.h" //CPU was actually a NSC800 (Z80 compatible)
49 #include "machine/i8279.h"
50 #include "machine/pit8253.h"
51 #include "sound/spkrdev.h"
52 #include "video/mc6845.h"
53 #include "emupal.h"
54 #include "screen.h"
55 #include "softlist.h"
56 #include "speaker.h"
57 #include "tilemap.h"
58 
59 
60 class i7000_state : public driver_device
61 {
62 public:
i7000_state(const machine_config & mconfig,device_type type,const char * tag)63 	i7000_state(const machine_config &mconfig, device_type type, const char *tag)
64 		: driver_device(mconfig, type, tag)
65 		, m_maincpu(*this, "maincpu")
66 		, m_card(*this, "cardslot")
67 		, m_gfxdecode(*this, "gfxdecode")
68 		, m_videoram(*this, "videoram")
69 		, m_kbd(*this, "X%u", 0U)
70 	{ }
71 
72 	void i7000(machine_config &config);
73 
74 protected:
75 	virtual void video_start() override;
76 	virtual void machine_start() override;
77 
78 private:
79 	required_device<cpu_device> m_maincpu;
80 	required_device<generic_slot_device> m_card;
81 	required_device<gfxdecode_device> m_gfxdecode;
82 	required_shared_ptr<uint8_t> m_videoram;
83 	required_ioport_array<8> m_kbd;
84 
85 	uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
86 	uint8_t m_row;
87 	tilemap_t *m_bg_tilemap;
88 
89 	TILE_GET_INFO_MEMBER(get_bg_tile_info);
90 	MC6845_ON_UPDATE_ADDR_CHANGED(crtc_addr);
91 	void i7000_palette(palette_device &palette) const;
92 	DECLARE_DEVICE_IMAGE_LOAD_MEMBER(card_load);
93 
94 	uint8_t kbd_r();
95 	void scanlines_w(uint8_t data);
96 
97 	void i7000_io(address_map &map);
98 	void i7000_mem(address_map &map);
99 };
100 
scanlines_w(uint8_t data)101 void i7000_state::scanlines_w(uint8_t data)
102 {
103 	m_row = data;
104 }
105 
kbd_r()106 uint8_t i7000_state::kbd_r()
107 {
108 	for (int i=0; i<40*25; i++){
109 		m_bg_tilemap->mark_tile_dirty(i);
110 	}
111 
112 	return m_kbd[m_row & 7]->read();
113 }
114 
115 /* Input ports */
116 static INPUT_PORTS_START( i7000 )
117 	PORT_START("X0")
PORT_CODE(KEYCODE_1)118 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1)
119 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9)
120 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U)
121 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC)
122 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K)
123 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N)
124 		PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("!") PORT_CHAR('!')
125 		PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("ENTER") PORT_CODE(KEYCODE_ENTER)
126 
127 	PORT_START("X1")
128 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2)
129 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0)
130 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T)
131 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0x9D")
132 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L)
133 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X)
134 		PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0x8F")
135 		PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("^R DC2") //0x12
136 
137 	PORT_START("X2")
138 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3)
139 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("$ ^") PORT_CHAR('$') PORT_CHAR('^')
140 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R)
141 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S)
142 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0xA0")
143 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C)
144 		PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("- _") PORT_CODE(KEYCODE_MINUS)
145 		PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("BACKSPACE") PORT_CODE(KEYCODE_BACKSPACE)
146 
147 	PORT_START("X3")
148 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4)
149 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("% +") PORT_CHAR('%') PORT_CHAR('+')
150 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I)
151 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D)
152 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0x9C")
153 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M)
154 		PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("]") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']')
155 		PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("@") PORT_CHAR('@')
156 
157 	PORT_START("X4")
158 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5 *") PORT_CODE(KEYCODE_5)
159 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("^U NAK") //0x15
160 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O)
161 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F)
162 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("| <") PORT_CHAR('<')
163 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(", ;") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
164 		PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[") PORT_CODE(KEYCODE_OPENBRACE)
165 		PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("^E ENQ") //0x05
166 
167 	PORT_START("X5")
168 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6)
169 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("^O SI") //0x0F
170 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P)
171 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G)
172 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J)
173 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.')
174 		PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("#") PORT_CHAR('#')
175 		PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("{") PORT_CHAR('{')
176 
177 	PORT_START("X6")
178 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7)
179 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q)
180 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E)
181 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A)
182 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H)
183 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V)
184 		PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("^L FF") //0x0C
185 		PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("^T DC4") //0x14
186 
187 	PORT_START("X7")
188 		PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8)
189 		PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W)
190 		PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y)
191 		PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(">") PORT_CHAR('>')
192 		PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z)
193 		PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B)
194 		PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("SPACEBAR") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
195 		PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("}") PORT_CHAR('}')
196 
197 	PORT_START("DSW") /* DP01 */
198 		PORT_DIPNAME( 0x80, 0x80, "1")
199 		PORT_DIPSETTING(    0x00, DEF_STR( No ) )
200 		PORT_DIPSETTING(    0x80, DEF_STR( Yes ) )
201 		PORT_DIPNAME( 0x40, 0x40, "2")
202 		PORT_DIPSETTING(    0x00, DEF_STR( No ) )
203 		PORT_DIPSETTING(    0x40, DEF_STR( Yes ) )
204 		PORT_DIPNAME( 0x20, 0x00, "3")
205 		PORT_DIPSETTING(    0x00, DEF_STR( No ) )
206 		PORT_DIPSETTING(    0x20, DEF_STR( Yes ) )
207 		PORT_DIPNAME( 0x10, 0x10, "4")
208 		PORT_DIPSETTING(    0x00, DEF_STR( No ) )
209 		PORT_DIPSETTING(    0x10, DEF_STR( Yes ) )
210 		PORT_DIPNAME( 0x08, 0x08, "5")
211 		PORT_DIPSETTING(    0x00, DEF_STR( No ) )
212 		PORT_DIPSETTING(    0x08, DEF_STR( Yes ) )
213 		PORT_DIPNAME( 0x04, 0x04, "6")
214 		PORT_DIPSETTING(    0x00, DEF_STR( No ) )
215 		PORT_DIPSETTING(    0x04, DEF_STR( Yes ) )
216 		PORT_DIPNAME( 0x02, 0x00, "7")
217 		PORT_DIPSETTING(    0x00, DEF_STR( No ) )
218 		PORT_DIPSETTING(    0x02, DEF_STR( Yes ) )
219 		PORT_DIPNAME( 0x01, 0x01, "8")
220 		PORT_DIPSETTING(    0x00, DEF_STR( No ) )
221 		PORT_DIPSETTING(    0x01, DEF_STR( Yes ) )
222 INPUT_PORTS_END
223 
224 
225 void i7000_state::machine_start()
226 {
227 	address_space &program = m_maincpu->space(AS_PROGRAM);
228 
229 	if (m_card->exists())
230 	{
231 		// 0x4000 - 0xbfff   32KB ROM
232 		program.install_read_handler(0x4000, 0xbfff, read8sm_delegate(*m_card, FUNC(generic_slot_device::read_rom)));
233 	}
234 }
235 
i7000_palette(palette_device & palette) const236 void i7000_state::i7000_palette(palette_device &palette) const
237 {
238 	palette.set_pen_color(0, rgb_t(0x33, 0x33, 0x33));
239 	palette.set_pen_color(1, rgb_t(0xBB, 0xBB, 0xBB));
240 }
241 
242 /*FIXME: we still need to figure out the proper memory map
243          for the maincpu and where the cartridge slot maps to. */
i7000_mem(address_map & map)244 void i7000_state::i7000_mem(address_map &map)
245 {
246 	map(0x0000, 0x0fff).rom().region("boot", 0);
247 	map(0x2000, 0x2fff).ram().share("videoram");
248 	map(0x4000, 0xffff).ram();
249 //  map(0x4000, 0xbfff).rom().region("cardslot", 0);
250 }
251 
i7000_io(address_map & map)252 void i7000_state::i7000_io(address_map &map)
253 {
254 	map.unmap_value_high();
255 	map.global_mask(0xff);
256 //  map(0x06, 0x06).w(FUNC(i7000_state::i7000_io_?_w));
257 //  map(0x08, 0x09).w(FUNC(i7000_state::i7000_io_?_w)); //printer perhaps?
258 //  map(0x0c, 0x0c).w(FUNC(i7000_state::i7000_io_?_w)); //0x0C and 0x10 may be related to mem page swapping. (self-test "4. PAG")
259 //  map(0x10, 0x10).w(FUNC(i7000_state::i7000_io_?_w));
260 //  map(0x14, 0x15).w(FUNC(i7000_state::i7000_io_?_w));
261 
262 	map(0x18, 0x1b).rw("pit8253", FUNC(pit8253_device::read), FUNC(pit8253_device::write));
263 
264 //  map(0x1c, 0x1c).w(FUNC(i7000_state::i7000_io_printer_data_w)); //ASCII data
265 	map(0x1d, 0x1d).portr("DSW");
266 //  map(0x1e, 0x1e).rw(FUNC(i7000_state::i7000_io_printer_status_r), FUNC(i7000_state::i7000_io_?_w));
267 //  map(0x1f, 0x1f).w(FUNC(i7000_state::i7000_io_printer_strobe_w)); //self-test routine writes 0x08 and 0x09 (it seems that bit 0 is the strobe and bit 3 is an enable signal)
268 //  map(0x20, 0x21).rw(FUNC(i7000_state::i7000_io_keyboard_r), FUNC(i7000_state::i7000_io_keyboard_w));
269 
270 	map(0x20, 0x21).rw("i8279", FUNC(i8279_device::read), FUNC(i8279_device::write));
271 
272 //  map(0x24, 0x24).r(FUNC(i7000_state::i7000_io_?_r));
273 //  map(0x25, 0x25).w(FUNC(i7000_state::i7000_io_?_w));
274 
275 //  map(0x28, 0x2d).rw(FUNC(i7000_state::i7000_io_joystick_r), FUNC(i7000_state::i7000_io_joystick_w));
276 
277 //  map(0x3b, 0x3b).w(FUNC(i7000_state::i7000_io_?_w));
278 //  map(0x66, 0x67).w(FUNC(i7000_state::i7000_io_?_w));
279 //  map(0xbb, 0xbb).w(FUNC(i7000_state::i7000_io_?_w)); //may be related to page-swapping...
280 }
281 
DEVICE_IMAGE_LOAD_MEMBER(i7000_state::card_load)282 DEVICE_IMAGE_LOAD_MEMBER(i7000_state::card_load)
283 {
284 	uint32_t size = m_card->common_get_size("rom");
285 
286 	m_card->rom_alloc(size, GENERIC_ROM8_WIDTH, ENDIANNESS_BIG);
287 	m_card->common_load_rom(m_card->get_rom_base(), size, "rom");
288 
289 	return image_init_result::PASS;
290 }
291 
292 static const gfx_layout i7000_charlayout =
293 {
294 	8, 8,                   /* 8 x 8 characters */
295 	256,                 /* 256 characters */
296 	1,                  /* 1 bits per pixel */
297 	{ 0 },                  /* no bitplanes */
298 	/* x offsets */
299 	{ 0, 1, 2, 3, 4, 5, 6, 7 },
300 	/* y offsets */
301 	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
302 	8*8                 /* every char takes 8 bytes */
303 };
304 
305 static GFXDECODE_START( gfx_i7000 )
306 	GFXDECODE_ENTRY( "gfx1", 0x0000, i7000_charlayout, 0, 8 )
307 GFXDECODE_END
308 
309 /****************************
310 * Video/Character functions *
311 ****************************/
312 
TILE_GET_INFO_MEMBER(i7000_state::get_bg_tile_info)313 TILE_GET_INFO_MEMBER(i7000_state::get_bg_tile_info)
314 {
315 	tileinfo.set(0, /*code:*/ m_videoram[tile_index], /*color:*/ 0, 0);
316 }
317 
video_start()318 void i7000_state::video_start()
319 {
320 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(i7000_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 40, 25);
321 }
322 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)323 uint32_t i7000_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
324 {
325 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
326 	return 0;
327 }
328 
329 /* ROCKWELL 6545 - Transparent Memory Addressing */
MC6845_ON_UPDATE_ADDR_CHANGED(i7000_state::crtc_addr)330 MC6845_ON_UPDATE_ADDR_CHANGED(i7000_state::crtc_addr)
331 {
332 	/* What is this mandatory function meant to do ? */
333 }
334 
335 
i7000(machine_config & config)336 void i7000_state::i7000(machine_config &config)
337 {
338 	/* basic machine hardware */
339 	NSC800(config, m_maincpu, XTAL(4'000'000));
340 	m_maincpu->set_addrmap(AS_PROGRAM, &i7000_state::i7000_mem);
341 	m_maincpu->set_addrmap(AS_IO, &i7000_state::i7000_io);
342 
343 	/* video hardware */
344 	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
345 	screen.set_refresh_hz(60);
346 	screen.set_size(320, 200); /* 40x25 8x8 chars */
347 	screen.set_visarea(0, 320-1, 0, 200-1);
348 	screen.set_screen_update(FUNC(i7000_state::screen_update));
349 	screen.set_palette("palette");
350 
351 	GFXDECODE(config, m_gfxdecode, "palette", gfx_i7000);
352 	PALETTE(config, "palette", FUNC(i7000_state::i7000_palette), 2);
353 
354 	r6545_1_device &crtc(R6545_1(config, "crtc", XTAL(20'000'000))); /* (?) */
355 	crtc.set_screen("screen");
356 	crtc.set_show_border_area(true);
357 	crtc.set_char_width(8);
358 	crtc.set_on_update_addr_change_callback(FUNC(i7000_state::crtc_addr));
359 
360 	/* sound hardware */
361 	SPEAKER(config, "mono").front_center();
362 	SPEAKER_SOUND(config, "speaker").add_route(ALL_OUTPUTS, "mono", 0.50);
363 
364 	/* Programmable timer */
365 	pit8253_device &pit8253(PIT8253(config, "pit8253", 0));
366 //  pit8253.set_clk<0>(XTAL(4'000'000) / 2); /* TODO: verify on PCB */
367 //  pit8253.out_handler<0>().set(FUNC(i7000_state::i7000_pit_out0));
368 //  pit8253.set_clk<1>(XTAL(4'000'000) / 2); /* TODO: verify on PCB */
369 //  pit8253.out_handler<1>().set(FUNC(i7000_state::i7000_pit_out1));
370 	pit8253.set_clk<2>(XTAL(4'000'000) / 2); /* TODO: verify on PCB */
371 	pit8253.out_handler<2>().set("speaker", FUNC(speaker_sound_device::level_w));
372 
373 	/* Keyboard interface */
374 	i8279_device &kbdc(I8279(config, "i8279", 4000000)); /* guessed value. TODO: verify on PCB */
375 	kbdc.out_sl_callback().set(FUNC(i7000_state::scanlines_w));         // scan SL lines
376 	kbdc.in_rl_callback().set(FUNC(i7000_state::kbd_r));                // kbd RL lines
377 	kbdc.in_shift_callback().set_constant(1);                           // TODO: Shift key
378 	kbdc.in_ctrl_callback().set_constant(1);                            // TODO: Ctrl key
379 
380 	/* Cartridge slot */
381 	GENERIC_CARTSLOT(config, "cardslot", generic_romram_plain_slot, "i7000_card", "rom").set_device_load(FUNC(i7000_state::card_load));
382 
383 	/* Software lists */
384 	SOFTWARE_LIST(config, "card_list").set_original("i7000_card");
385 }
386 
387 ROM_START( i7000 )
388 	ROM_REGION( 0x1000, "boot", 0 )
389 	ROM_LOAD( "i7000_boot_v1_4r02_15_10_85_d52d.rom",  0x0000, 0x1000, CRC(622412e5) SHA1(bf187a095600fd46a739c35132a85b5f39b2f867) )
390 
391 	ROM_REGION( 0x0800, "gfx1", 0 )
392 	ROM_LOAD( "i7000_chargen.rom", 0x0000, 0x0800, CRC(fb7383e9) SHA1(71a6561bb9ff3cbf74711fa7ab445f9b43f15626) )
393 		/*
394 		The character generator ROM originally dumped had
395 		some corrupt data that was manually fixed:
396 
397 		ROM address | Originally dumped value | Manually fixed value | Comment
398 		    0x06A2 |                    0xF7 | 0xFE                 | This is a fix to the upper right portion of a 2x2 tile image of a big filled circle
399 		    0x06A3 |                    0xF7 | 0xFE                 | This is another fix to the same tile (character value: 0xD4)
400 
401 		Also, characters 0x05, 0x06, 0x07 and 0x08
402 		as well as lowercase 'x' (0x78), uppercase 'Y' (0x59)
403 		may contain corrupt data, but we can't be sure,
404 		unless we find another Itautec I7000 computer and
405 		redump it's ROMs to double-check.
406 	*/
407 
408 	ROM_REGION( 0x1000, "drive", 0 )
409 	ROM_LOAD( "i7000_drive_ci01.rom", 0x0000, 0x1000, CRC(d8d6e5c1) SHA1(93e7db42fbfaa8243973321c7fc8c51ed80780be) )
410 
411 	ROM_REGION( 0x1000, "telex", 0 )
412 	ROM_LOAD( "i7000_telex_ci09.rom", 0x0000, 0x1000, CRC(c1c8fcc8) SHA1(cbf5fb600e587b998f190a9e3fb398a51d8a5e87) )
413 ROM_END
414 
415 //    YEAR  NAME   PARENT  COMPAT  MACHINE  INPUT  CLASS        INIT        COMPANY    FULLNAME  FLAGS
416 COMP( 1982, i7000, 0,      0,      i7000,   i7000, i7000_state, empty_init, "Itautec", "I-7000", MACHINE_NOT_WORKING)
417