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