1 // license:BSD-3-Clause
2 // copyright-holders:Barry Rodewald
3 /*
4 * attache.c
5 *
6 * Created on: 17/05/2013
7 *
8 * Driver by Barry Rodewald
9 *
10 *
11 * Otrona Attache
12 *
13 * CPU: Zilog Z80-A, 4MHz
14 * RAM: 64kB
15 * DMA: AMD 9517A (or compatible)
16 * RTC: Oki MSM5832, Z80-PIO
17 * Sound: GI AY-3-8912
18 * FDC: NEC D765A, 5.25" floppies
19 * Video: CRT5027, 320x240
20 * Serial: Z80-SIO, two RS-232C or RS-422/423 ports
21 *
22 * Note:
23 * In terminal mode (when disk booting fails or no disk is inserted), press Ctrl+Linefeed (ctrl+pgdn by default)
24 * to enter monitor mode. From here you can run a bunch of diagnostic tests.
25 *
26 * G - Display Test Pattern
27 * H - Display RAM Test
28 * nnI - Input Test (nn = port number)
29 * J - Jump
30 * K - Keyboard Test
31 * L - Loop Tests
32 * M - Map Test
33 * nnmmO - Output Test (nn = port number, mm = data to send)
34 * P - Format Diskette (P to format disk in Drive A, 1P for Drive B)
35 * Q - CMOS RAM Test
36 * nR - Main RAM Test (n = 16kB bank to test [0-3])
37 * bbpcS - Select Output Ports (first b = printer baud rate, second b = comm baud rate, p = printer port, c = comm port)
38 * T - Real Time Clock Test
39 * U - United Tests
40 * cchsV - Read a sector from disk (cc = cylinder, h = head [bit 0=drive, bit 2=side], s = sector)
41 * cchsW - Write a sector from disk
42 * nnnnmmmmX - I/O port transmit (nnnn = number of bytes to transmit, mmmm = start of data to transmit)
43 * nnnnY - I/O port receive (nnnn = address of data loaded)
44 * Z - Auto Disk Test (1Z for drive B)
45 *
46 * For the 8086 board (will display an 'x' if the 8086 board is not installed):
47 * [ - 8086 RAM Test
48 * ] - SCC Test
49 * ( - GPIB Listener/Talker Test
50 * ) - GPIB Controller Test
51 *
52 * The Attache 8:16 is an upgraded Attache adding an 8086 (+ optional 8087) board with its own 256kB of RAM,
53 * and optionally a GPIB controller (TMS9914A) and serial synchronous port (Z8530 SCC). It also has modifications
54 * to the main Z80 board, specifically the display circuitry, adding a high-resolution display, and replacing
55 * the character ROM with a larger ROM containing an IBM character set.
56 * It effectively allows the Attache to run MS-DOS and use a 10MB hard disk.
57 *
58 * TODO:
59 * - Keyboard repeat
60 * - Get at least some of the system tests to pass
61 * - and probably lots more I've forgotten, too.
62 * - improve Z80-8086 comms on the 8:16, saving a file to the RAM disk under CP/M often ends in deadlock.
63 * - add Z8530 SCC and TMS9914A GPIB to the 8:16. These are optional devices, so aren't strictly required at this stage.
64 * - connect dma and sio (channel 3)
65 */
66
67 #include "emu.h"
68
69 #include "cpu/z80/z80.h"
70 #include "machine/z80daisy.h"
71 #include "bus/rs232/rs232.h"
72 #include "imagedev/floppy.h"
73 #include "machine/am9517a.h"
74 #include "machine/msm5832.h"
75 #include "machine/nvram.h"
76 #include "machine/ram.h"
77 #include "machine/upd765.h"
78 #include "machine/z80ctc.h"
79 #include "machine/z80sio.h"
80 #include "machine/z80pio.h"
81 #include "machine/i8255.h"
82 #include "cpu/i86/i86.h"
83 #include "sound/ay8910.h"
84 #include "video/tms9927.h"
85 #include "emupal.h"
86 #include "screen.h"
87 #include "softlist.h"
88 #include "speaker.h"
89
90
91 class attache_state : public driver_device
92 {
93 public:
attache_state(const machine_config & mconfig,device_type type,const char * tag)94 attache_state(const machine_config &mconfig, device_type type, const char *tag)
95 : driver_device(mconfig, type, tag)
96 , m_maincpu(*this, "maincpu")
97 , m_rom(*this, "boot")
98 , m_ram(*this, RAM_TAG)
99 , m_char_rom(*this, "video")
100 , m_rtc(*this, "rtc")
101 , m_psg(*this, "psg")
102 , m_fdc(*this, "fdc")
103 , m_sio(*this, "sio")
104 , m_pio(*this, "pio")
105 , m_ctc(*this, "ctc")
106 , m_crtc(*this, "crtc")
107 , m_dma(*this, "dma")
108 , m_palette(*this, "palette")
109 , m_floppy0(*this, "fdc:0:525dd")
110 , m_floppy1(*this, "fdc:1:525dd")
111 , m_kb_rows(*this, "row%u", 0U)
112 , m_kb_mod(*this, "modifiers")
113 , m_membank1(*this, "bank1")
114 , m_membank2(*this, "bank2")
115 , m_membank3(*this, "bank3")
116 , m_membank4(*this, "bank4")
117 , m_membank5(*this, "bank5")
118 , m_membank6(*this, "bank6")
119 , m_membank7(*this, "bank7")
120 , m_membank8(*this, "bank8")
121 , m_nvram(*this, "nvram")
122 , m_rom_active(true)
123 , m_gfx_enabled(false)
124 , m_kb_clock(true)
125 , m_kb_empty(true)
126 { }
127
128 void attache(machine_config &config);
129
130 uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
131
132 uint8_t pio_portA_r();
133 uint8_t pio_portB_r();
134 void pio_portA_w(uint8_t data);
135 void pio_portB_w(uint8_t data);
136
137 uint8_t dma_mem_r(offs_t offset);
138 void dma_mem_w(offs_t offset, uint8_t data);
139
140 uint8_t fdc_dma_r();
141 void fdc_dma_w(uint8_t data);
142
143 DECLARE_WRITE_LINE_MEMBER(hreq_w);
144 DECLARE_WRITE_LINE_MEMBER(eop_w);
145 DECLARE_WRITE_LINE_MEMBER(fdc_dack_w);
146
147 protected:
148 // PIO port B operation select
149 enum
150 {
151 PIO_SEL_8910_ADDR = 0,
152 PIO_SEL_8910_DATA,
153 PIO_SEL_5832_READ,
154 PIO_SEL_5832_WRITE,
155 PIO_SEL_5101_WRITE,
156 PIO_SEL_5101_READ,
157 PIO_SEL_LATCH,
158 PIO_SEL_NOP
159 };
160
161 // Display controller operation select
162 enum
163 {
164 DISP_GFX_0 = 0,
165 DISP_GFX_1,
166 DISP_GFX_2,
167 DISP_GFX_3,
168 DISP_GFX_4,
169 DISP_CRTC,
170 DISP_ATTR,
171 DISP_CHAR
172 };
173
174 // overrides
175 virtual void driver_start() override;
176 virtual void machine_start() override;
177 virtual void machine_reset() override;
178
179 uint8_t rom_r(offs_t offset);
180 void rom_w(offs_t offset, uint8_t data);
181
182 void display_command_w(uint8_t data);
183 uint8_t display_data_r(offs_t offset);
184 void display_data_w(offs_t offset, uint8_t data);
185 uint8_t dma_mask_r();
186 void dma_mask_w(uint8_t data);
187
188 uint8_t memmap_r();
189 void memmap_w(uint8_t data);
190
191 void operation_strobe(uint8_t data);
192 void keyboard_clock_w(bool state);
193 uint8_t keyboard_data_r();
194 uint16_t get_key();
195
196 void attache_io(address_map &map);
197 void attache_map(address_map &map);
198
199 required_device<z80_device> m_maincpu;
200 required_memory_region m_rom;
201 required_device<ram_device> m_ram;
202 required_memory_region m_char_rom;
203 required_device<msm5832_device> m_rtc;
204 required_device<ay8912_device> m_psg;
205 required_device<upd765a_device> m_fdc;
206 required_device<z80sio_device> m_sio;
207 required_device<z80pio_device> m_pio;
208 required_device<z80ctc_device> m_ctc;
209 required_device<tms9927_device> m_crtc;
210 required_device<am9517a_device> m_dma;
211 required_device<palette_device> m_palette;
212 required_device<floppy_image_device> m_floppy0;
213 required_device<floppy_image_device> m_floppy1;
214 required_ioport_array<8> m_kb_rows;
215 required_ioport m_kb_mod;
216 required_memory_bank m_membank1;
217 required_memory_bank m_membank2;
218 required_memory_bank m_membank3;
219 required_memory_bank m_membank4;
220 required_memory_bank m_membank5;
221 required_memory_bank m_membank6;
222 required_memory_bank m_membank7;
223 required_memory_bank m_membank8;
224 required_device<nvram_device> m_nvram;
225
226 bool m_rom_active;
227 bool m_gfx_enabled;
228 uint8_t m_pio_porta;
229 uint8_t m_pio_portb;
230 uint8_t m_pio_select;
231 uint8_t m_pio_latch;
232 uint8_t m_crtc_reg_select;
233 uint8_t m_current_cmd;
234 uint8_t m_char_ram[128*32];
235 uint8_t m_attr_ram[128*32];
236 uint8_t m_gfx_ram[128*32*5];
237 uint8_t m_char_line;
238 uint8_t m_attr_line;
239 uint8_t m_gfx_line;
240 uint8_t m_cmos_ram[64];
241 uint8_t m_cmos_select;
242 uint16_t m_kb_current_key;
243 bool m_kb_clock;
244 bool m_kb_empty;
245 uint8_t m_kb_bitpos;
246 uint8_t m_memmap;
247 };
248
249 class attache816_state : public attache_state
250 {
251 public:
attache816_state(const machine_config & mconfig,device_type type,const char * tag)252 attache816_state(const machine_config &mconfig, device_type type, const char *tag)
253 : attache_state(mconfig, type, tag)
254 , m_extcpu(*this,"extcpu")
255 , m_ppi(*this,"ppi")
256 , m_comms_val(0)
257 , m_x86_irq_enable(0)
258 , m_z80_rx_ready(false)
259 , m_z80_tx_ready(false)
260 { }
261
262 void attache816(machine_config &config);
263
264 private:
265 void x86_comms_w(uint8_t data);
266 uint8_t x86_comms_r();
267 void x86_irq_enable(uint8_t data);
268 void x86_iobf_enable_w(offs_t offset, uint8_t data);
269 uint8_t z80_comms_r();
270 void z80_comms_w(uint8_t data);
271 uint8_t z80_comms_status_r();
272 void z80_comms_ctrl_w(uint8_t data);
273 DECLARE_WRITE_LINE_MEMBER(ppi_irq);
274 DECLARE_WRITE_LINE_MEMBER(x86_dsr);
275
276 virtual void machine_reset() override;
277
278 void attache816_io(address_map &map);
279 void attache_x86_io(address_map &map);
280 void attache_x86_map(address_map &map);
281
282 required_device<cpu_device> m_extcpu;
283 required_device<i8255_device> m_ppi;
284
285 uint8_t m_comms_val;
286 uint8_t m_x86_irq_enable;
287 bool m_z80_rx_ready;
288 bool m_z80_tx_ready;
289 };
290
291 // Attributes (based on schematics):
292 // bit 0 = ALT
293 // bit 1 = RW
294 // bit 2 = BKG (reverse?)
295 // bit 3 = brightness
296 // bit 4 = double-size (width)
297 // bit 5 = underline
298 // bit 6 = superscript
299 // bit 7 = subscript (superscript and subscript combined produces strikethrough)
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)300 uint32_t attache_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
301 {
302 // Graphics output (if enabled)
303 if(m_gfx_enabled)
304 {
305 pen_t const *const pen = m_palette->pens();
306
307 for(uint8_t y=0;y<(bitmap.height()-1)/10;y++)
308 {
309 for(uint8_t x=0;x<(bitmap.width()-1)/8;x++)
310 {
311 // graphics pixels use half the clock of text, so 4 graphics pixels per character
312 for(uint8_t scan=0;scan<10;scan+=2)
313 {
314 uint8_t const data = m_gfx_ram[(128*32*(scan/2))+(y*128+x)];
315 bitmap.pix(y*10+scan,x*8) = pen[BIT(data,7)];
316 bitmap.pix(y*10+scan,x*8+1) = pen[BIT(data,7)];
317 bitmap.pix(y*10+scan,x*8+2) = pen[BIT(data,6)];
318 bitmap.pix(y*10+scan,x*8+3) = pen[BIT(data,6)];
319 bitmap.pix(y*10+scan,x*8+4) = pen[BIT(data,5)];
320 bitmap.pix(y*10+scan,x*8+5) = pen[BIT(data,5)];
321 bitmap.pix(y*10+scan,x*8+6) = pen[BIT(data,4)];
322 bitmap.pix(y*10+scan,x*8+7) = pen[BIT(data,4)];
323 bitmap.pix(y*10+scan+1,x*8) = pen[BIT(data,3)];
324 bitmap.pix(y*10+scan+1,x*8+1) = pen[BIT(data,3)];
325 bitmap.pix(y*10+scan+1,x*8+2) = pen[BIT(data,2)];
326 bitmap.pix(y*10+scan+1,x*8+3) = pen[BIT(data,2)];
327 bitmap.pix(y*10+scan+1,x*8+4) = pen[BIT(data,1)];
328 bitmap.pix(y*10+scan+1,x*8+5) = pen[BIT(data,1)];
329 bitmap.pix(y*10+scan+1,x*8+6) = pen[BIT(data,0)];
330 bitmap.pix(y*10+scan+1,x*8+7) = pen[BIT(data,0)];
331 }
332 }
333 }
334 }
335 else
336 bitmap.fill(0);
337
338 // Text output
339 uint8_t dbl_mode = 0; // detemines which half of character to display when using double size attribute,
340 // as it can start on either odd or even character cells.
341 for(uint8_t y=0;y<(bitmap.height()-1)/10;y++) // lines
342 {
343 uint8_t const start = m_crtc->upscroll_offset();
344 uint8_t const vy = (start + y) % 24;
345
346 for(uint8_t x=0;x<(bitmap.width()-1)/8;x++) // columns
347 {
348 assert(((y*128)+x) >= 0 && ((y*128)+x) < ARRAY_LENGTH(m_char_ram));
349 assert(((vy*128)+x) >= 0 && ((vy*128)+x) < ARRAY_LENGTH(m_char_ram));
350 uint8_t ch = m_char_ram[(vy*128)+x];
351 pen_t fg = m_palette->pen(m_attr_ram[(vy*128)+x] & 0x08 ? 2 : 1); // brightness
352 if(m_attr_ram[(vy*128)+x] & 0x10) // double-size
353 dbl_mode++;
354 else
355 dbl_mode = 0;
356
357 for(uint8_t scan=0;scan<10;scan++) // 10 scanlines per line
358 {
359 uint8_t data = m_char_rom->base()[(ch*16+scan)];
360 if((m_attr_ram[(vy*128)+x] & 0xc0) != 0xc0) // if not strikethrough
361 {
362 if(m_attr_ram[(vy*128)+x] & 0x40) // superscript
363 {
364 if(scan >= 5)
365 data = 0;
366 else
367 data = m_char_rom->base()[ch*16+(scan*2)+1];
368 }
369 if(m_attr_ram[(vy*128)+x] & 0x80) // subscript
370 {
371 if(scan < 5)
372 data = 0;
373 else
374 data = m_char_rom->base()[ch*16+((scan-5)*2)+1];
375 }
376 }
377 if((m_attr_ram[(vy*128)+x] & 0x20) && scan == 9) // underline
378 data = 0xff;
379 if((m_attr_ram[(vy*128)+x] & 0xc0) == 0xc0 && scan == 3) // strikethrough
380 data = 0xff;
381 if(m_attr_ram[(vy*128)+x] & 0x04) // reverse
382 data = ~data;
383 if(m_attr_ram[(vy*128)+x] & 0x10) // double-size
384 {
385 uint8_t newdata = 0;
386 if(dbl_mode & 1)
387 {
388 newdata = (data & 0x80) | ((data & 0x80) >> 1)
389 | ((data & 0x40) >> 1) | ((data & 0x40) >> 2)
390 | ((data & 0x20) >> 2) | ((data & 0x20) >> 3)
391 | ((data & 0x10) >> 3) | ((data & 0x10) >> 4);
392 }
393 else
394 {
395 newdata = ((data & 0x08) << 4) | ((data & 0x08) << 3)
396 | ((data & 0x04) << 3) | ((data & 0x04) << 2)
397 | ((data & 0x02) << 2) | ((data & 0x02) << 1)
398 | ((data & 0x01) << 1) | (data & 0x01);
399 }
400 data = newdata;
401 }
402
403 for(uint8_t bit=0;bit<8;bit++) // 8 pixels per character
404 {
405 uint16_t const xpos = x*8+bit;
406 uint16_t const ypos = y*10+scan;
407
408 if(BIT(data,7-bit))
409 bitmap.pix(ypos,xpos) = fg;
410 }
411 }
412 }
413 }
414 return 0;
415 }
416
rom_r(offs_t offset)417 uint8_t attache_state::rom_r(offs_t offset)
418 {
419 if(m_rom_active)
420 return m_rom->base()[offset];
421 else
422 return m_ram->pointer()[m_membank1->entry()*0x2000 + offset];
423 }
424
rom_w(offs_t offset,uint8_t data)425 void attache_state::rom_w(offs_t offset, uint8_t data)
426 {
427 m_ram->pointer()[m_membank1->entry()*0x2000 + offset] = data;
428 }
429
get_key()430 uint16_t attache_state::get_key()
431 {
432 uint8_t row,bits,data;
433 uint8_t res = 0;
434
435 // scan input ports
436 for(row=0;row<8;row++)
437 {
438 data = m_kb_rows[row]->read();
439 for(bits=0;bits<8;bits++)
440 {
441 if(BIT(data,bits))
442 {
443 res = bits & 0x07;
444 res |= ((row & 0x07) << 3);
445 m_kb_empty = false;
446 data = m_kb_mod->read();
447 if(~data & 0x01)
448 res |= 0x80; // shift
449 if(data & 0x02)
450 res |= 0x40; // ctrl
451 //logerror("KB: hit row %i, bit %i\n",row,bits);
452 return res;
453 }
454 }
455 }
456 // no key pressed
457 m_kb_empty = true;
458 return res;
459 }
460
keyboard_data_r()461 uint8_t attache_state::keyboard_data_r()
462 {
463 uint16_t key;
464 if(m_kb_bitpos == 1) // start bit, if data is available
465 {
466 key = get_key();
467 if(m_kb_current_key != key)
468 m_kb_current_key = key;
469 else
470 return 0x00;
471 //logerror("KB: bit position %i, key %02x, empty %i\n",m_kb_bitpos,m_kb_current_key,m_kb_empty);
472 if(m_kb_empty)
473 return 0x00;
474 else
475 return 0x40;
476 }
477 else
478 {
479 //logerror("KB: bit position %i, key %02x, empty %i\n",m_kb_bitpos,m_kb_current_key,m_kb_empty);
480 if(m_kb_current_key & (1<<(m_kb_bitpos-2)))
481 return 0x00;
482 else
483 return 0x40;
484 }
485 }
486
keyboard_clock_w(bool state)487 void attache_state::keyboard_clock_w(bool state)
488 {
489 if(!state && m_kb_clock) // high to low transition - advance bit position
490 {
491 m_kb_bitpos++;
492 if(m_kb_bitpos > 9)
493 m_kb_bitpos = 1;
494 }
495 m_kb_clock = state;
496 }
497
498 // TODO: Figure out exactly how the HLD, RD, WR and CS lines on the RTC are hooked up
pio_portA_r()499 uint8_t attache_state::pio_portA_r()
500 {
501 uint8_t ret = 0xff;
502 uint8_t porta = m_pio_porta;
503
504 switch(m_pio_select)
505 {
506 case PIO_SEL_8910_DATA:
507 ret = m_psg->data_r();
508 logerror("PSG: data read %02x\n",ret);
509 break;
510 case PIO_SEL_5832_WRITE:
511 m_rtc->cs_w(1);
512 m_rtc->write_w(0);
513 m_rtc->read_w(1);
514 m_rtc->address_w((porta & 0xf0) >> 4);
515 ret = m_rtc->data_r();
516 logerror("RTC: read %02x from %02x (write)\n",ret,(porta & 0xf0) >> 4);
517 break;
518 case PIO_SEL_5832_READ:
519 m_rtc->cs_w(1);
520 m_rtc->write_w(0);
521 m_rtc->read_w(1);
522 m_rtc->address_w((porta & 0xf0) >> 4);
523 ret = m_rtc->data_r();
524 logerror("RTC: read %02x from %02x\n",ret,(porta & 0xf0) >> 4);
525 break;
526 case PIO_SEL_5101_WRITE:
527 m_cmos_select = (m_cmos_select & 0xf0) | ((porta & 0xf0) >> 4);
528 ret = m_cmos_ram[m_cmos_select] & 0x0f;
529 logerror("CMOS: read %02x from byte %02x (write)\n",ret, m_cmos_select);
530 break;
531 case PIO_SEL_5101_READ:
532 m_cmos_select = (m_cmos_select & 0xf0) | ((porta & 0xf0) >> 4);
533 ret = m_cmos_ram[m_cmos_select] & 0x0f;
534 logerror("CMOS: read %02x from byte %02x\n",ret, m_cmos_select);
535 break;
536 case PIO_SEL_LATCH:
537 ret = 0x00; // Write-only?
538 break;
539 case PIO_SEL_NOP:
540 logerror("PIO: NOP read\n");
541 break;
542 }
543 //logerror("PIO: Port A read operation %i returning %02x\n",m_pio_select,ret);
544
545 return ret;
546 }
547
pio_portB_r()548 uint8_t attache_state::pio_portB_r()
549 {
550 uint8_t ret = m_pio_portb & 0xbf;
551 ret |= keyboard_data_r();
552 return ret;
553 }
554
operation_strobe(uint8_t data)555 void attache_state::operation_strobe(uint8_t data)
556 {
557 //logerror("PIO: Port A write operation %i, data %02x\n",m_pio_select,data);
558 switch(m_pio_select)
559 {
560 case PIO_SEL_8910_ADDR:
561 m_psg->address_w(data);
562 break;
563 case PIO_SEL_8910_DATA:
564 m_psg->data_w(data);
565 break;
566 case PIO_SEL_5832_WRITE:
567 m_rtc->cs_w(1);
568 m_rtc->read_w(0);
569 m_rtc->address_w((data & 0xf0) >> 4);
570 m_rtc->data_w(data & 0x0f);
571 m_rtc->write_w(1);
572 logerror("RTC: write %01x to %01x\n",data & 0x0f,(data & 0xf0) >> 4);
573 break;
574 case PIO_SEL_5832_READ:
575 m_rtc->cs_w(1);
576 m_rtc->write_w(0);
577 m_rtc->read_w(0);
578 m_rtc->address_w((data & 0xf0) >> 4);
579 logerror("RTC: write %01x to %01x (read)\n",data & 0x0f,(data & 0xf0) >> 4);
580 break;
581 case PIO_SEL_5101_WRITE:
582 m_cmos_select = (m_cmos_select & 0xf0) | ((data & 0xf0) >> 4);
583 m_cmos_ram[m_cmos_select] = data & 0x0f;
584 logerror("CMOS: write %01x to byte %02x\n",data & 0x0f, m_cmos_select);
585 break;
586 case PIO_SEL_5101_READ:
587 m_cmos_select = (m_cmos_select & 0xf0) | ((data & 0xf0) >> 4);
588 logerror("CMOS: write %01x to byte %02x (read)\n",data & 0x0f, m_cmos_select);
589 break;
590 case PIO_SEL_LATCH:
591 m_pio_latch = data;
592 m_rom_active = ~data & 0x04;
593 m_floppy0->mon_w((data & 0x01) ? 0 : 1);
594 m_floppy1->mon_w((data & 0x01) ? 0 : 1);
595 m_gfx_enabled = data & 0x02;
596 // TODO: display brightness
597 break;
598 case PIO_SEL_NOP:
599 logerror("PIO: NOP write\n");
600 break;
601 default:
602 logerror("PIO: Invalid write operation %i, data %02x\n",m_pio_select,data);
603 }
604 }
605
pio_portA_w(uint8_t data)606 void attache_state::pio_portA_w(uint8_t data)
607 {
608 // AO-7 = LATCH DATA OUT:
609 // LO = MOTOR ON
610 // L1 = GRAPHICS ENABLE
611 // L2 = /EPROM ENABLE
612 // L3-7 = DISPLAY BRIGHTNESS
613 // AO-7 = 8910 DATA I/O:
614 // AO-3 = 5832 DO-3 I/O
615 // A4-7 = 5832 AO-3 OUT
616 // AO-3 = 5101 DO-3 I/O
617 // A4-7 = 5101 AO-3 OUT
618 m_pio_porta = data;
619 }
620
pio_portB_w(uint8_t data)621 void attache_state::pio_portB_w(uint8_t data)
622 {
623 // BO-1 = 5101 A4-5
624 // B2-4 = OPERATION SELECT
625 // 0 = 8910 ADDR LOAD
626 // 1 = 8910 DATA LOAD
627 // 2 = 5832 WRITE -- the CP/M BIOS dumped from an actual disc seems to switch the RTC operations around
628 // 3 = 5832 READ this differs from the BIOS source listings available for both CP/M 2.2.3 and 2.2.5
629 // 4 = 5101 WRITE
630 // 5 = 5101 READ
631 // 6 = LATCH LOAD
632 // 7 = NO-OP
633 //B5 = /'138 OPERATION STROBE
634 //B6 = /KEYBOARD DATA IN
635 //B7 = /KEYBOARD CLOCK OUT
636 m_cmos_select = ((data & 0x03) << 4) | (m_cmos_select & 0x0f);
637 if(!(data & 0x20) && (m_pio_portb & 0x20))
638 {
639 m_pio_select = (data & 0x1c) >> 2;
640 operation_strobe(m_pio_porta);
641 }
642 m_pio_portb = data;
643 keyboard_clock_w(data & 0x80);
644 }
645
646 // Display uses A8-A15 placed on the bus by the OUT instruction as an extra parameter
display_data_r(offs_t offset)647 uint8_t attache_state::display_data_r(offs_t offset)
648 {
649 uint8_t ret = 0xff;
650 uint8_t param = (offset & 0xff00) >> 8;
651
652 switch(m_current_cmd)
653 {
654 case DISP_GFX_0:
655 ret = m_gfx_ram[(m_gfx_line*128)+(param & 0x7f)];
656 break;
657 case DISP_GFX_1:
658 ret = m_gfx_ram[(m_gfx_line*128)+(param & 0x7f)+(128*32)];
659 break;
660 case DISP_GFX_2:
661 ret = m_gfx_ram[(m_gfx_line*128)+(param & 0x7f)+(128*32*2)];
662 break;
663 case DISP_GFX_3:
664 ret = m_gfx_ram[(m_gfx_line*128)+(param & 0x7f)+(128*32*3)];
665 break;
666 case DISP_GFX_4:
667 ret = m_gfx_ram[(m_gfx_line*128)+(param & 0x7f)+(128*32*4)];
668 break;
669 case DISP_CRTC:
670 ret = m_crtc->read(m_crtc_reg_select);
671 break;
672 case DISP_ATTR:
673 ret = m_attr_ram[(m_attr_line*128)+(param & 0x7f)];
674 break;
675 case DISP_CHAR:
676 ret = m_char_ram[(m_char_line*128)+(param & 0x7f)];
677 break;
678 default:
679 logerror("Unimplemented display operation %02x\n",m_current_cmd);
680 }
681
682 return ret;
683 }
684
display_data_w(offs_t offset,uint8_t data)685 void attache_state::display_data_w(offs_t offset, uint8_t data)
686 {
687 uint8_t param = (offset & 0xff00) >> 8;
688 switch(m_current_cmd)
689 {
690 case DISP_GFX_0:
691 m_gfx_ram[(m_gfx_line*128)+(param & 0x7f)] = data;
692 break;
693 case DISP_GFX_1:
694 m_gfx_ram[(m_gfx_line*128)+(param & 0x7f)+(128*32)] = data;
695 break;
696 case DISP_GFX_2:
697 m_gfx_ram[(m_gfx_line*128)+(param & 0x7f)+(128*32*2)] = data;
698 break;
699 case DISP_GFX_3:
700 m_gfx_ram[(m_gfx_line*128)+(param & 0x7f)+(128*32*3)] = data;
701 break;
702 case DISP_GFX_4:
703 m_gfx_ram[(m_gfx_line*128)+(param & 0x7f)+(128*32*4)] = data;
704 break;
705 case DISP_CRTC:
706 m_crtc->write(m_crtc_reg_select, data);
707 //logerror("CRTC: write reg %02x, data %02x\n",m_crtc_reg_select,data);
708 break;
709 case DISP_ATTR:
710 m_attr_ram[(m_attr_line*128)+(param & 0x7f)] = data;
711 break;
712 case DISP_CHAR:
713 m_char_ram[(m_char_line*128)+(param & 0x7f)] = data;
714 break;
715 // default:
716 // logerror("Unimplemented display operation %02x data %02x param %02x\n",m_current_cmd,data,param);
717 }
718 }
719
display_command_w(uint8_t data)720 void attache_state::display_command_w(uint8_t data)
721 {
722 uint8_t cmd = (data & 0xe0) >> 5;
723
724 m_current_cmd = cmd;
725
726 switch(cmd)
727 {
728 case DISP_GFX_0:
729 case DISP_GFX_1:
730 case DISP_GFX_2:
731 case DISP_GFX_3:
732 case DISP_GFX_4:
733 m_gfx_line = data & 0x1f;
734 break;
735 case DISP_CRTC:
736 // CRT5027/TMS9927 registers
737 m_crtc_reg_select = data & 0x0f;
738 break;
739 case DISP_ATTR:
740 // Attribute RAM
741 m_attr_line = data & 0x1f;
742 break;
743 case DISP_CHAR:
744 // Character RAM
745 m_char_line = data & 0x1f;
746 break;
747 }
748 }
749
memmap_r()750 uint8_t attache_state::memmap_r()
751 {
752 return m_memmap;
753 }
754
memmap_w(uint8_t data)755 void attache_state::memmap_w(uint8_t data)
756 {
757 // TODO: figure this out properly
758 // Tech manual says that RAM is split into 8kB chunks.
759 // Would seem that bit 4 is always 0 and bit 3 is always 1?
760 uint8_t bank = (data & 0xe0) >> 5;
761 uint8_t loc = data & 0x07;
762 memory_bank* banknum[8] = { m_membank1, m_membank2, m_membank3, m_membank4, m_membank5, m_membank6, m_membank7, m_membank8 };
763 m_memmap = data;
764
765 banknum[bank]->set_entry(loc);
766
767 logerror("MEM: write %02x - bank %i, location %i\n",data, bank, loc);
768 }
769
dma_mask_r()770 uint8_t attache_state::dma_mask_r()
771 {
772 return m_dma->read(0x0f);
773 }
774
dma_mask_w(uint8_t data)775 void attache_state::dma_mask_w(uint8_t data)
776 {
777 m_dma->write(0x0f,data);
778 }
779
fdc_dma_r()780 uint8_t attache_state::fdc_dma_r()
781 {
782 uint8_t ret = m_fdc->dma_r();
783 return ret;
784 }
785
fdc_dma_w(uint8_t data)786 void attache_state::fdc_dma_w(uint8_t data)
787 {
788 m_fdc->dma_w(data);
789 }
790
dma_mem_r(offs_t offset)791 uint8_t attache_state::dma_mem_r(offs_t offset)
792 {
793 return m_maincpu->space(AS_PROGRAM).read_byte(offset);
794 }
795
dma_mem_w(offs_t offset,uint8_t data)796 void attache_state::dma_mem_w(offs_t offset, uint8_t data)
797 {
798 m_maincpu->space(AS_PROGRAM).write_byte(offset,data);
799 }
800
WRITE_LINE_MEMBER(attache_state::hreq_w)801 WRITE_LINE_MEMBER( attache_state::hreq_w )
802 {
803 m_maincpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
804
805 m_dma->hack_w(state);
806 }
807
WRITE_LINE_MEMBER(attache_state::eop_w)808 WRITE_LINE_MEMBER(attache_state::eop_w)
809 {
810 m_fdc->tc_w(state);
811 }
812
WRITE_LINE_MEMBER(attache_state::fdc_dack_w)813 WRITE_LINE_MEMBER( attache_state::fdc_dack_w )
814 {
815 }
816
817 /*
818 * Z80 <-> 8086 communication
819 */
820
x86_comms_w(uint8_t data)821 void attache816_state::x86_comms_w(uint8_t data)
822 {
823 m_comms_val = data;
824 m_ppi->pc6_w(1);
825 m_z80_rx_ready = false;
826 }
827
x86_comms_r()828 uint8_t attache816_state::x86_comms_r()
829 {
830 m_z80_tx_ready = false;
831 m_ppi->pc4_w(1);
832 return m_comms_val;
833 }
834
835 // PPI Port B - IRQ enable
836 // bit 0: i8255A PPI
837 // bit 1: TMS9914A GPIB
838 // bit 2: Z8530 SCC
839 // bit 3: 8087 FPU
840 // bit 4: enable WAIT logic
841 // bit 5: enable high-resolution graphics
x86_irq_enable(uint8_t data)842 void attache816_state::x86_irq_enable(uint8_t data)
843 {
844 m_x86_irq_enable = data;
845 }
846
x86_iobf_enable_w(offs_t offset,uint8_t data)847 void attache816_state::x86_iobf_enable_w(offs_t offset, uint8_t data)
848 {
849 switch(offset)
850 {
851 case 0x00:
852 m_ppi->pc6_w(0);
853 break;
854 case 0x01:
855 m_ppi->pc6_w(1);
856 break;
857 case 0x04:
858 m_ppi->pc4_w(0);
859 break;
860 case 0x05:
861 m_ppi->pc4_w(1);
862 break;
863 default:
864 logerror("Invalid x86 IRQ enable write offset %02x data %02x\n",offset,data);
865 }
866 }
867
z80_comms_r()868 uint8_t attache816_state::z80_comms_r()
869 {
870 m_z80_rx_ready = true;
871 m_ppi->pc6_w(0);
872 return m_comms_val;
873 }
874
z80_comms_w(uint8_t data)875 void attache816_state::z80_comms_w(uint8_t data)
876 {
877 m_comms_val = data;
878 m_z80_tx_ready = true;
879 m_ppi->pc4_w(0);
880 }
881
882 // Z80 comms status
883 // bit 0: set if no data is ready
884 // bit 1: set if ready to accept data
z80_comms_status_r()885 uint8_t attache816_state::z80_comms_status_r()
886 {
887 uint8_t ret = 0xf0; // low nibble always high?
888
889 if(m_z80_rx_ready)
890 ret |= 0x01;
891 if(m_z80_tx_ready)
892 ret |= 0x02;
893
894 return ret;
895 }
896
897 // Z80 comms controller
898 // bit 0: Reset 8086
z80_comms_ctrl_w(uint8_t data)899 void attache816_state::z80_comms_ctrl_w(uint8_t data)
900 {
901 m_extcpu->set_input_line(INPUT_LINE_RESET,(data & 0x01) ? ASSERT_LINE : CLEAR_LINE);
902 }
903
WRITE_LINE_MEMBER(attache816_state::ppi_irq)904 WRITE_LINE_MEMBER(attache816_state::ppi_irq)
905 {
906 if(m_x86_irq_enable & 0x01)
907 m_extcpu->set_input_line_and_vector(0,state,0x03); // I8086
908 }
909
WRITE_LINE_MEMBER(attache816_state::x86_dsr)910 WRITE_LINE_MEMBER(attache816_state::x86_dsr)
911 {
912 // TODO: /DSR to Z8530 SCC
913 }
914
attache_map(address_map & map)915 void attache_state::attache_map(address_map &map)
916 {
917 map(0x0000, 0x1fff).bankrw("bank1");
918 map(0x2000, 0x3fff).bankrw("bank2");
919 map(0x4000, 0x5fff).bankrw("bank3");
920 map(0x6000, 0x7fff).bankrw("bank4");
921 map(0x8000, 0x9fff).bankrw("bank5");
922 map(0xa000, 0xbfff).bankrw("bank6");
923 map(0xc000, 0xdfff).bankrw("bank7");
924 map(0xe000, 0xffff).bankrw("bank8");
925 }
926
attache_io(address_map & map)927 void attache_state::attache_io(address_map &map)
928 {
929 map(0xe0, 0xed).rw(m_dma, FUNC(am9517a_device::read), FUNC(am9517a_device::write)).mirror(0xff00);
930 map(0xee, 0xee).w(FUNC(attache_state::display_command_w)).mirror(0xff00);
931 map(0xef, 0xef).rw(FUNC(attache_state::dma_mask_r), FUNC(attache_state::dma_mask_w)).mirror(0xff00);
932 map(0xf0, 0xf1).rw(m_sio, FUNC(z80sio_device::ba_cd_r), FUNC(z80sio_device::ba_cd_w)).mirror(0xff00);
933 map(0xf4, 0xf7).rw(m_ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write)).mirror(0xff00);
934 map(0xf8, 0xfb).rw(m_pio, FUNC(z80pio_device::read_alt), FUNC(z80pio_device::write_alt)).mirror(0xff00);
935 map(0xfc, 0xfd).m(m_fdc, FUNC(upd765a_device::map)).mirror(0xff00);
936 map(0xfe, 0xfe).rw(FUNC(attache_state::display_data_r), FUNC(attache_state::display_data_w)).select(0xff00);
937 map(0xff, 0xff).rw(FUNC(attache_state::memmap_r), FUNC(attache_state::memmap_w)).mirror(0xff00);
938 }
939
attache816_io(address_map & map)940 void attache816_state::attache816_io(address_map &map)
941 {
942 map(0xb8, 0xb8).rw(FUNC(attache816_state::z80_comms_status_r), FUNC(attache816_state::z80_comms_ctrl_w)).mirror(0xff00);
943 map(0xb9, 0xb9).rw(FUNC(attache816_state::z80_comms_r), FUNC(attache816_state::z80_comms_w)).mirror(0xff00);
944 map(0xe0, 0xed).rw(m_dma, FUNC(am9517a_device::read), FUNC(am9517a_device::write)).mirror(0xff00);
945 map(0xee, 0xee).w(FUNC(attache816_state::display_command_w)).mirror(0xff00);
946 map(0xef, 0xef).rw(FUNC(attache816_state::dma_mask_r), FUNC(attache816_state::dma_mask_w)).mirror(0xff00);
947 map(0xf0, 0xf1).rw(m_sio, FUNC(z80sio_device::ba_cd_r), FUNC(z80sio_device::ba_cd_w)).mirror(0xff00);
948 map(0xf4, 0xf7).rw(m_ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write)).mirror(0xff00);
949 map(0xf8, 0xfb).rw(m_pio, FUNC(z80pio_device::read_alt), FUNC(z80pio_device::write_alt)).mirror(0xff00);
950 map(0xfc, 0xfd).m(m_fdc, FUNC(upd765a_device::map)).mirror(0xff00);
951 map(0xfe, 0xfe).rw(FUNC(attache816_state::display_data_r), FUNC(attache816_state::display_data_w)).select(0xff00);
952 map(0xff, 0xff).rw(FUNC(attache816_state::memmap_r), FUNC(attache816_state::memmap_w)).mirror(0xff00);
953 }
954
attache_x86_map(address_map & map)955 void attache816_state::attache_x86_map(address_map &map)
956 {
957 map(0x00000, 0x3ffff).ram();
958 map(0xb0000, 0xbffff).noprw(); // triggers IRQ?
959 map(0xfe000, 0xfffff).rom().region("x86bios", 0x0000);
960 }
961
attache_x86_io(address_map & map)962 void attache816_state::attache_x86_io(address_map &map)
963 {
964 map(0x100, 0x107).rw(m_ppi, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0x00ff);
965 map(0x108, 0x10d).w(FUNC(attache816_state::x86_iobf_enable_w));
966 // 0x140/2/4/6 - Z8530 SCC serial
967 // 0x180/2/4/6/8/a/c/e - GPIB (TMS9914A)
968 }
969
970 static INPUT_PORTS_START(attache)
971 PORT_START("row0")
972 PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("BS") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
973 PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("TAB") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9)
974 PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("LF") PORT_CODE(KEYCODE_PGDN) PORT_CHAR(10)
975 PORT_BIT(0x18,IP_ACTIVE_HIGH,IPT_UNUSED)
976 PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
977 PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_UNUSED)
978 PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("LOCK") PORT_CODE(KEYCODE_PGUP)
979
980 PORT_START("row1")
981 PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
982 PORT_BIT(0x06,IP_ACTIVE_HIGH,IPT_UNUSED)
983 PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27)
984 PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
985 PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
986 PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Up") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
987 PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
988
989 PORT_START("row2")
990 PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0 ^") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('^')
991 PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1 !") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
992 PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2 @") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
993 PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
994 PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4 $") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
995 PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5 %") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
996 PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6 &") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
997 PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7 *") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('*')
998
999 PORT_START("row3")
1000 PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8 (") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
1001 PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9 )") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
1002 PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("' \"") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
1003 PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("; :") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
1004 PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
1005 PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("= +") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
1006 PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
1007 PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
1008
1009 PORT_START("row4")
1010 PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("` ~") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
1011 PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
1012 PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
1013 PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
1014 PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
1015 PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
1016 PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
1017 PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
1018
1019 PORT_START("row5")
1020 PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
1021 PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
1022 PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
1023 PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
1024 PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
1025 PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
1026 PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
1027 PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
1028
1029 PORT_START("row6")
1030 PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
1031 PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
1032 PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
1033 PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
1034 PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
1035 PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
1036 PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
1037 PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
1038
1039 PORT_START("row7")
1040 PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
1041 PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
1042 PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
1043 PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("[ {") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
1044 PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("\\ |") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
1045 PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("] }") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
1046 PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("- _") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
1047 PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
1048
1049 PORT_START("modifiers")
1050 PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
1051 PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
1052 INPUT_PORTS_END
1053
1054 // IRQ daisy chain = CTC -> SIO -> Expansion
1055 static const z80_daisy_config attache_daisy_chain[] =
1056 {
1057 { "ctc" },
1058 { "sio" },
1059 // expansion
1060 { nullptr }
1061 };
1062
attache_floppies(device_slot_interface & device)1063 static void attache_floppies(device_slot_interface &device)
1064 {
1065 device.option_add("525dd", FLOPPY_525_DD);
1066 }
1067
driver_start()1068 void attache_state::driver_start()
1069 {
1070 uint8_t *RAM = m_ram->pointer();
1071
1072 m_membank1->configure_entries(0, 8, &RAM[0x0000], 0x2000);
1073 m_membank2->configure_entries(0, 8, &RAM[0x0000], 0x2000);
1074 m_membank3->configure_entries(0, 8, &RAM[0x0000], 0x2000);
1075 m_membank4->configure_entries(0, 8, &RAM[0x0000], 0x2000);
1076 m_membank5->configure_entries(0, 8, &RAM[0x0000], 0x2000);
1077 m_membank6->configure_entries(0, 8, &RAM[0x0000], 0x2000);
1078 m_membank7->configure_entries(0, 8, &RAM[0x0000], 0x2000);
1079 m_membank8->configure_entries(0, 8, &RAM[0x0000], 0x2000);
1080
1081 m_membank1->set_entry(0);
1082 m_membank2->set_entry(1);
1083 m_membank3->set_entry(2);
1084 m_membank4->set_entry(3);
1085 m_membank5->set_entry(4);
1086 m_membank6->set_entry(5);
1087 m_membank7->set_entry(6);
1088 m_membank8->set_entry(7);
1089
1090 memset(RAM,0,65536);
1091
1092 m_nvram->set_base(m_cmos_ram,64);
1093
1094 m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0000,0x0fff, read8sm_delegate(*this, FUNC(attache_state::rom_r)), write8sm_delegate(*this, FUNC(attache_state::rom_w)));
1095
1096 save_pointer(m_char_ram,"Character RAM",128*32);
1097 save_pointer(m_attr_ram,"Attribute RAM",128*32);
1098 save_pointer(m_gfx_ram,"Graphics RAM",128*32*5);
1099 save_pointer(m_cmos_ram,"CMOS RAM",64);
1100 }
1101
machine_start()1102 void attache_state::machine_start()
1103 {
1104 // initialise RAM
1105 memset(m_cmos_ram,0,64);
1106 memset(m_attr_ram,0,128*32);
1107 memset(m_char_ram,0,128*32);
1108 memset(m_gfx_ram,0,128*32*5);
1109 }
1110
machine_reset()1111 void attache_state::machine_reset()
1112 {
1113 m_kb_bitpos = 0;
1114 }
1115
machine_reset()1116 void attache816_state::machine_reset()
1117 {
1118 attache_state::machine_reset();
1119 }
1120
attache(machine_config & config)1121 void attache_state::attache(machine_config &config)
1122 {
1123 Z80(config, m_maincpu, 8_MHz_XTAL / 2);
1124 m_maincpu->set_addrmap(AS_PROGRAM, &attache_state::attache_map);
1125 m_maincpu->set_addrmap(AS_IO, &attache_state::attache_io);
1126 m_maincpu->set_daisy_config(attache_daisy_chain);
1127
1128 config.set_maximum_quantum(attotime::from_hz(60));
1129
1130 screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER, rgb_t::green()));
1131 screen.set_raw(12.324_MHz_XTAL, 784, 0, 640, 262, 0, 240);
1132 screen.set_screen_update(FUNC(attache_state::screen_update));
1133
1134 PALETTE(config, m_palette, palette_device::MONOCHROME_HIGHLIGHT);
1135
1136 SPEAKER(config, "mono").front_center();
1137 AY8912(config, m_psg, 8_MHz_XTAL / 4);
1138 m_psg->add_route(ALL_OUTPUTS, "mono", 0.25);
1139
1140 MSM5832(config, m_rtc, 32.768_kHz_XTAL);
1141
1142 Z80PIO(config, m_pio, 8_MHz_XTAL / 2);
1143 m_pio->in_pa_callback().set(FUNC(attache_state::pio_portA_r));
1144 m_pio->out_pa_callback().set(FUNC(attache_state::pio_portA_w));
1145 m_pio->in_pb_callback().set(FUNC(attache_state::pio_portB_r));
1146 m_pio->out_pb_callback().set(FUNC(attache_state::pio_portB_w));
1147
1148 Z80SIO(config, m_sio, 8_MHz_XTAL / 2);
1149 m_sio->out_txda_callback().set("rs232a", FUNC(rs232_port_device::write_txd));
1150 m_sio->out_rtsa_callback().set("rs232a", FUNC(rs232_port_device::write_rts));
1151 m_sio->out_txdb_callback().set("rs232b", FUNC(rs232_port_device::write_txd));
1152 m_sio->out_rtsb_callback().set("rs232b", FUNC(rs232_port_device::write_rts));
1153 m_sio->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
1154
1155 rs232_port_device &rs232a(RS232_PORT(config, "rs232a", default_rs232_devices, nullptr));
1156 rs232a.rxd_handler().set(m_sio, FUNC(z80sio_device::rxa_w));
1157 rs232a.cts_handler().set(m_sio, FUNC(z80sio_device::ctsa_w));
1158
1159 rs232_port_device &rs232b(RS232_PORT(config, "rs232b", default_rs232_devices, nullptr));
1160 rs232b.rxd_handler().set(m_sio, FUNC(z80sio_device::rxb_w));
1161 rs232b.cts_handler().set(m_sio, FUNC(z80sio_device::ctsb_w));
1162
1163 Z80CTC(config, m_ctc, 8_MHz_XTAL / 2);
1164 m_ctc->set_clk<0>(8_MHz_XTAL / 26); // 307.692 KHz
1165 m_ctc->set_clk<1>(8_MHz_XTAL / 26); // 307.692 KHz
1166 m_ctc->zc_callback<0>().set(m_sio, FUNC(z80sio_device::rxca_w));
1167 m_ctc->zc_callback<0>().append(m_sio, FUNC(z80sio_device::txca_w));
1168 m_ctc->zc_callback<1>().set(m_sio, FUNC(z80sio_device::rxtxcb_w));
1169 m_ctc->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
1170
1171 AM9517A(config, m_dma, 8_MHz_XTAL / 4);
1172 m_dma->out_hreq_callback().set(FUNC(attache_state::hreq_w));
1173 m_dma->out_eop_callback().set(FUNC(attache_state::eop_w));
1174 m_dma->in_memr_callback().set(FUNC(attache_state::dma_mem_r));
1175 m_dma->out_memw_callback().set(FUNC(attache_state::dma_mem_w));
1176 m_dma->in_ior_callback<0>().set(FUNC(attache_state::fdc_dma_r));
1177 m_dma->out_iow_callback<0>().set(FUNC(attache_state::fdc_dma_w));
1178 // m_dma->out_dack_callback<0>().set(FUNC(attache_state::fdc_dack_w));
1179
1180 UPD765A(config, m_fdc, 8_MHz_XTAL, true, true);
1181 m_fdc->intrq_wr_callback().set(m_ctc, FUNC(z80ctc_device::trg3));
1182 m_fdc->drq_wr_callback().set(m_dma, FUNC(am9517a_device::dreq0_w)).invert();
1183 FLOPPY_CONNECTOR(config, "fdc:0", attache_floppies, "525dd", floppy_image_device::default_floppy_formats);
1184 FLOPPY_CONNECTOR(config, "fdc:1", attache_floppies, "525dd", floppy_image_device::default_floppy_formats);
1185
1186 TMS9927(config, m_crtc, 12.324_MHz_XTAL / 8);
1187 m_crtc->set_char_width(8);
1188 m_crtc->vsyn_callback().set(m_ctc, FUNC(z80ctc_device::trg2));
1189 m_crtc->set_screen("screen");
1190
1191 NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
1192
1193 RAM(config, RAM_TAG).set_default_size("64K");
1194
1195 SOFTWARE_LIST(config, "disk_list").set_original("attache");
1196 }
1197
attache816(machine_config & config)1198 void attache816_state::attache816(machine_config &config)
1199 {
1200 Z80(config, m_maincpu, 8_MHz_XTAL / 2);
1201 m_maincpu->set_addrmap(AS_PROGRAM, &attache816_state::attache_map);
1202 m_maincpu->set_addrmap(AS_IO, &attache816_state::attache_io);
1203 m_maincpu->set_daisy_config(attache_daisy_chain);
1204
1205 config.set_maximum_quantum(attotime::from_hz(60));
1206
1207 I8086(config, m_extcpu, 24_MHz_XTAL / 3);
1208 m_extcpu->set_addrmap(AS_PROGRAM, &attache816_state::attache_x86_map);
1209 m_extcpu->set_addrmap(AS_IO, &attache816_state::attache_x86_io);
1210 config.set_perfect_quantum(m_extcpu);
1211
1212 screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER, rgb_t::green()));
1213 screen.set_raw(12.324_MHz_XTAL, 784, 0, 640, 262, 0, 240);
1214 screen.set_screen_update(FUNC(attache_state::screen_update));
1215
1216 PALETTE(config, m_palette, palette_device::MONOCHROME_HIGHLIGHT);
1217
1218 SPEAKER(config, "mono").front_center();
1219 AY8912(config, m_psg, 8_MHz_XTAL / 4);
1220 m_psg->add_route(ALL_OUTPUTS, "mono", 0.25);
1221
1222 MSM5832(config, m_rtc, 32.768_kHz_XTAL);
1223
1224 Z80PIO(config, m_pio, 8_MHz_XTAL / 2);
1225 m_pio->in_pa_callback().set(FUNC(attache_state::pio_portA_r));
1226 m_pio->out_pa_callback().set(FUNC(attache_state::pio_portA_w));
1227 m_pio->in_pb_callback().set(FUNC(attache_state::pio_portB_r));
1228 m_pio->out_pb_callback().set(FUNC(attache_state::pio_portB_w));
1229
1230 Z80SIO(config, m_sio, 8_MHz_XTAL / 2);
1231 m_sio->out_txda_callback().set("rs232a", FUNC(rs232_port_device::write_txd));
1232 m_sio->out_rtsa_callback().set("rs232a", FUNC(rs232_port_device::write_rts));
1233 m_sio->out_txdb_callback().set("rs232b", FUNC(rs232_port_device::write_txd));
1234 m_sio->out_rtsb_callback().set("rs232b", FUNC(rs232_port_device::write_rts));
1235 m_sio->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
1236
1237 rs232_port_device &rs232a(RS232_PORT(config, "rs232a", default_rs232_devices, nullptr));
1238 rs232a.rxd_handler().set(m_sio, FUNC(z80sio_device::rxa_w));
1239 rs232a.cts_handler().set(m_sio, FUNC(z80sio_device::ctsa_w));
1240
1241 rs232_port_device &rs232b(RS232_PORT(config, "rs232b", default_rs232_devices, nullptr));
1242 rs232b.rxd_handler().set(m_sio, FUNC(z80sio_device::rxb_w));
1243 rs232b.cts_handler().set(m_sio, FUNC(z80sio_device::ctsb_w));
1244
1245 Z80CTC(config, m_ctc, 8_MHz_XTAL / 2);
1246 m_ctc->set_clk<0>(8_MHz_XTAL / 26); // 307.692 KHz
1247 m_ctc->set_clk<1>(8_MHz_XTAL / 26); // 307.692 KHz
1248 m_ctc->zc_callback<0>().set(m_sio, FUNC(z80sio_device::rxca_w));
1249 m_ctc->zc_callback<0>().append(m_sio, FUNC(z80sio_device::txca_w));
1250 m_ctc->zc_callback<1>().set(m_sio, FUNC(z80sio_device::rxtxcb_w));
1251 m_ctc->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
1252
1253 I8255A(config, m_ppi, 0);
1254 m_ppi->out_pa_callback().set(FUNC(attache816_state::x86_comms_w));
1255 m_ppi->in_pa_callback().set(FUNC(attache816_state::x86_comms_r));
1256 m_ppi->out_pb_callback().set(FUNC(attache816_state::x86_irq_enable));
1257 m_ppi->out_pc_callback().set(FUNC(attache816_state::x86_dsr)).bit(0);
1258 m_ppi->out_pc_callback().append(FUNC(attache816_state::ppi_irq)).bit(7).invert();
1259
1260 AM9517A(config, m_dma, 8_MHz_XTAL / 4);
1261 m_dma->out_hreq_callback().set(FUNC(attache_state::hreq_w));
1262 m_dma->out_eop_callback().set(FUNC(attache_state::eop_w));
1263 m_dma->in_memr_callback().set(FUNC(attache_state::dma_mem_r));
1264 m_dma->out_memw_callback().set(FUNC(attache_state::dma_mem_w));
1265 m_dma->in_ior_callback<0>().set(FUNC(attache_state::fdc_dma_r));
1266 m_dma->out_iow_callback<0>().set(FUNC(attache_state::fdc_dma_w));
1267 // m_dma->out_dack_callback<0>().set(FUNC(attache_state::fdc_dack_w));
1268
1269 UPD765A(config, m_fdc, 8_MHz_XTAL, true, true);
1270 m_fdc->intrq_wr_callback().set(m_ctc, FUNC(z80ctc_device::trg3));
1271 m_fdc->drq_wr_callback().set(m_dma, FUNC(am9517a_device::dreq0_w)).invert();
1272 FLOPPY_CONNECTOR(config, "fdc:0", attache_floppies, "525dd", floppy_image_device::default_floppy_formats);
1273 FLOPPY_CONNECTOR(config, "fdc:1", attache_floppies, "525dd", floppy_image_device::default_floppy_formats);
1274
1275 TMS9927(config, m_crtc, 12.324_MHz_XTAL / 8);
1276 m_crtc->set_char_width(8);
1277 m_crtc->vsyn_callback().set(m_ctc, FUNC(z80ctc_device::trg2));
1278 m_crtc->set_screen("screen");
1279
1280 NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
1281
1282 RAM(config, RAM_TAG).set_default_size("64K");
1283
1284 SOFTWARE_LIST(config, "disk_list").set_original("attache");
1285 }
1286
1287 ROM_START( attache )
1288 ROM_REGION(0x10000, "maincpu", 0)
1289 ROM_FILL(0x0000,0x10000,0x00)
1290
1291 ROM_REGION(0x1000, "boot", 0)
1292 ROM_SYSTEM_BIOS(0, "u252revh", "Boot Rev.H")
1293 ROMX_LOAD("u252revh.bin", 0x0000, 0x1000, CRC(a06f0bdf) SHA1(d526cf23bfe0f8f9bcde812cd864a2a4cbc8b673), ROM_BIOS(0))
1294 ROM_SYSTEM_BIOS(1, "u252revg", "Boot Rev.G")
1295 ROMX_LOAD("u252revg.bin", 0x0000, 0x1000, CRC(113136b7) SHA1(845afd9ed2fd2b28c39921d8f2ba99e5295e0330), ROM_BIOS(1))
1296 ROM_SYSTEM_BIOS(2, "u252revf", "Boot Rev.F")
1297 ROMX_LOAD("u252revf.bin", 0x0000, 0x1000, CRC(b49eb3b2) SHA1(5b1b348301b2f76b1f250ba68bb8733fc15d18c2), ROM_BIOS(2))
1298
1299 ROM_REGION(0x1000, "video", 0)
1300 ROM_LOAD("u416vid.bin", 0x0000, 0x1000, CRC(e376ec59) SHA1(7b9e9db575e77ce2f479eb9ae913528e4f0d125d) )
1301
1302 ROM_REGION(0x100, "attr", 0)
1303 ROM_LOAD("u413.bin", 0x0000, 0x0100, CRC(5b60e622) SHA1(43450c747db1394466eabe5c26a61bf75a4f3b52) )
1304
1305 ROM_REGION(0x200, "iosel", 0)
1306 ROM_LOAD("u110.bin", 0x0000, 0x0200, CRC(70dd255a) SHA1(36dcce07a2c14eefc069433459c422341bd47efb) )
1307
1308 ROM_REGION(0x100, "floppy", 0)
1309 ROM_LOAD("u630.bin", 0x0000, 0x0100, CRC(f7a5c821) SHA1(fea07d9ac7e4e5f4f72aa7b2159deaedbd662ead) )
1310
1311 ROM_END
1312
1313 ROM_START( attache816 )
1314 ROM_REGION(0x10000, "maincpu", 0)
1315 ROM_FILL(0x0000,0x10000,0x00)
1316
1317 ROM_REGION(0x1000, "boot", 0)
1318 ROM_SYSTEM_BIOS(0, "u252revh", "Boot Rev.H")
1319 ROMX_LOAD("u252revh.bin", 0x0000, 0x1000, CRC(a06f0bdf) SHA1(d526cf23bfe0f8f9bcde812cd864a2a4cbc8b673), ROM_BIOS(0))
1320 ROM_SYSTEM_BIOS(1, "u252revg", "Boot Rev.G")
1321 ROMX_LOAD("u252revg.bin", 0x0000, 0x1000, CRC(113136b7) SHA1(845afd9ed2fd2b28c39921d8f2ba99e5295e0330), ROM_BIOS(1))
1322 ROM_SYSTEM_BIOS(2, "u252revf", "Boot Rev.F")
1323 ROMX_LOAD("u252revf.bin", 0x0000, 0x1000, CRC(b49eb3b2) SHA1(5b1b348301b2f76b1f250ba68bb8733fc15d18c2), ROM_BIOS(2))
1324
1325 ROM_REGION(0x2000, "video", 0)
1326 ROM_LOAD("u416vid2.bin", 0x0000, 0x2000, CRC(0bdaed8d) SHA1(eee1e8505906e7c3587ecdf9dd9227a2a3b3cdd4) )
1327
1328 ROM_REGION(0x100, "attr", 0)
1329 ROM_LOAD("u413.bin", 0x0000, 0x0100, CRC(5b60e622) SHA1(43450c747db1394466eabe5c26a61bf75a4f3b52) )
1330
1331 ROM_REGION(0x200, "iosel", 0)
1332 ROM_LOAD("u110.bin", 0x0000, 0x0200, CRC(70dd255a) SHA1(36dcce07a2c14eefc069433459c422341bd47efb) )
1333
1334 ROM_REGION(0x100, "floppy", 0)
1335 ROM_LOAD("u630.bin", 0x0000, 0x0100, CRC(f7a5c821) SHA1(fea07d9ac7e4e5f4f72aa7b2159deaedbd662ead) )
1336
1337 // chip locations based on schematics
1338 ROM_REGION16_LE(0x2000, "x86bios", 0)
1339 ROM_LOAD16_BYTE("u4.bin", 0x0000, 0x1000, CRC(658c8f93) SHA1(ce4b388af5b73884194f548afa706964305462f7) )
1340 ROM_LOAD16_BYTE("u9.bin", 0x0001, 0x1000, CRC(cc4cd938) SHA1(6a1d316628641f9b4de5c8c46f9430ef5bd6120f) )
1341
1342 ROM_END
1343
1344 // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
1345 COMP( 1982, attache, 0, 0, attache, attache, attache_state, empty_init, "Otrona", "Attach\xC3\xA9", MACHINE_IMPERFECT_GRAPHICS )
1346 COMP( 1983, attache816, attache, 0, attache816, attache, attache816_state, empty_init, "Otrona", "Attach\xC3\xA9 8:16", MACHINE_IMPERFECT_GRAPHICS )
1347