From 78c8d33ebdb5c51f93bec64a9c3d9ffd96fcd0b7 Mon Sep 17 00:00:00 2001 From: cracyc Date: Wed, 9 Sep 2015 22:15:46 -0500 Subject: [PATCH] pcd: implement pcx video device [Carl, Axel Muhr] --- scripts/target/mame/mess.lua | 1 + src/emu/video/scn2674.c | 163 +++++++++------ src/emu/video/scn2674.h | 4 + src/mess/drivers/pcd.c | 201 +++---------------- src/mess/machine/pcd_kbd.c | 2 + src/mess/video/pcd.c | 373 +++++++++++++++++++++++++++++++++++ src/mess/video/pcd.h | 95 +++++++++ 7 files changed, 597 insertions(+), 242 deletions(-) create mode 100644 src/mess/video/pcd.c create mode 100644 src/mess/video/pcd.h diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 57febc33335..34125b7f535 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -2212,6 +2212,7 @@ createMESSProjects(_target, _subtarget, "siemens") files { MAME_DIR .. "src/mess/drivers/pcd.c", MAME_DIR .. "src/mess/machine/pcd_kbd.c", + MAME_DIR .. "src/mess/video/pcd.c", } createMESSProjects(_target, _subtarget, "slicer") diff --git a/src/emu/video/scn2674.c b/src/emu/video/scn2674.c index 8dbc0f403e0..e1998367762 100644 --- a/src/emu/video/scn2674.c +++ b/src/emu/video/scn2674.c @@ -38,6 +38,8 @@ void scn2674_device::device_start() save_item(NAME(m_linecounter)); save_item(NAME(m_screen2_l)); save_item(NAME(m_screen2_h)); + save_item(NAME(m_cursor_l)); + save_item(NAME(m_cursor_h)); } void scn2674_device::device_reset() @@ -94,10 +96,12 @@ void scn2674_device::device_reset() m_spl1= 0; m_spl2= 0; m_dbl1= 0; + m_buffer= 0; m_linecounter= 0; m_irq_state= 0; m_IR_pointer = 0; m_address = 0; + m_start1change = 0; m_hpixels_per_column = m_text_hpixels_per_column; } @@ -246,8 +250,7 @@ void scn2674_device::write_init_regs(UINT8 data) break; } - if(m_display_enabled) - recompute_parameters(); + recompute_parameters(); m_IR_pointer++; if (m_IR_pointer>14)m_IR_pointer=14; @@ -291,8 +294,7 @@ void scn2674_device::write_command(UINT8 data) /* Disable GFX */ LOG2674(("disable GFX %02x\n",data)); m_gfx_enabled = 0; - if(m_display_enabled) - recompute_parameters(); + recompute_parameters(); } if ((data&0xe3)==0x23) @@ -300,8 +302,7 @@ void scn2674_device::write_command(UINT8 data) /* Enable GFX */ LOG2674(("enable GFX %02x\n",data)); m_gfx_enabled = 1; - if(m_display_enabled) - recompute_parameters(); + recompute_parameters(); } if ((data&0xe9)==0x28) @@ -410,59 +411,70 @@ void scn2674_device::write_command(UINT8 data) /* Delayed Commands */ /* These set 0x20 in status register when done */ - - if (data == 0xa4) + // These use the pointer address according to the datasheet but the pcx expects the screen start 2 address instead + switch(data) { - /* read at pointer address */ - LOG2674(("DELAYED read at pointer address %02x\n",data)); - } + case 0xa4: + /* read at pointer address */ + m_buffer = space().read_byte(m_screen2_l | (m_screen2_h << 8)); + LOG2674(("DELAYED read at pointer address %02x\n",data)); + break; - if (data == 0xa2) - { - /* write at pointer address */ - LOG2674(("DELAYED write at pointer address %02x\n",data)); - } + case 0xa2: + /* write at pointer address */ + space().write_byte(m_screen2_l | (m_screen2_h << 8), m_buffer); + LOG2674(("DELAYED write at pointer address %02x\n",data)); + break; - if (data == 0xa9) - { - /* increase cursor address */ - LOG2674(("DELAYED increase cursor address %02x\n",data)); - } + case 0xa9: + /* increment cursor address */ + if(!(++m_cursor_l)) + m_cursor_h++; + LOG2674(("DELAYED increase cursor address %02x\n",data)); + break; - if (data == 0xac) - { - /* read at cursor address */ - LOG2674(("DELAYED read at cursor address %02x\n",data)); - } + case 0xac: + /* read at cursor address */ + m_buffer = space().read_byte(m_cursor_l | (m_cursor_h << 8)); + LOG2674(("DELAYED read at cursor address %02x\n",data)); + break; - if (data == 0xaa) - { - /* write at cursor address */ - LOG2674(("DELAYED write at cursor address %02x\n",data)); - } + case 0xaa: + /* write at cursor address */ + space().write_byte(m_cursor_l | (m_cursor_h << 8), m_buffer); + LOG2674(("DELAYED write at cursor address %02x\n",data)); + break; - if (data == 0xad) - { - /* read at cursor address + increment */ - LOG2674(("DELAYED read at cursor address+increment %02x\n",data)); - } + case 0xad: + /* read at cursor address + increment */ + m_buffer = space().read_byte(m_cursor_l | (m_cursor_h << 8)); + if(!(++m_cursor_l)) + m_cursor_h++; + LOG2674(("DELAYED read at cursor address+increment %02x\n",data)); + break; - if (data == 0xab) - { - /* write at cursor address + increment */ - LOG2674(("DELAYED write at cursor address+increment %02x\n",data)); - } + case 0xab: + /* write at cursor address + increment */ + space().write_byte(m_cursor_l | (m_cursor_h << 8), m_buffer); + if(!(++m_cursor_l)) + m_cursor_h++; + LOG2674(("DELAYED write at cursor address+increment %02x\n",data)); + break; - if (data == 0xbb) - { - /* write from cursor address to pointer address */ - LOG2674(("DELAYED write from cursor address to pointer address %02x\n",data)); - } + case 0xbb: + /* write from cursor address to pointer address TODO: transfer only during blank*/ + for(i = m_cursor_l | (m_cursor_h << 8); i != (m_screen2_l | (m_screen2_h << 8)); i = ((i + 1) & 0xffff)) + space().write_byte(i, m_buffer); + space().write_byte(i, m_buffer); // get the last + m_cursor_l = m_screen2_l; + m_cursor_h = m_screen2_h; + LOG2674(("DELAYED write from cursor address to pointer address %02x\n",data)); + break; - if (data == 0xbd) - { - /* read from cursor address to pointer address */ - LOG2674(("DELAYED read from cursor address to pointer address %02x\n",data)); + case 0xbd: + /* read from cursor address to pointer address */ + LOG2674(("DELAYED read from cursor address to pointer address %02x\n",data)); + break; } } @@ -540,7 +552,11 @@ WRITE8_MEMBER( scn2674_device::write ) write_command(data); break; - case 2: m_screen1_l = data; break; + case 2: + m_screen1_l = data; + if(!m_screen->vblank()) + m_start1change = (m_linecounter / m_IR0_scanline_per_char_row) + 1; + break; case 3: m_screen1_h = data; m_dbl1=(data & 0xc0)>>6; @@ -550,6 +566,8 @@ WRITE8_MEMBER( scn2674_device::write ) m_screen1_h &= 0x3f; LOG2674(("IR14 - Double 1 overridden %02x\n",m_IR14_double_1)); } + if(!m_screen->vblank()) + m_start1change = (m_linecounter / m_IR0_scanline_per_char_row) + 1; break; case 4: m_cursor_l = data; break; @@ -572,6 +590,12 @@ void scn2674_device::recompute_parameters() int max_visible_x = (m_IR5_character_per_row * m_hpixels_per_column) - 1; int max_visible_y = (m_IR4_rows_per_screen * m_IR0_scanline_per_char_row) - 1; + if(!horiz_pix_total || !vert_pix_total) + { + m_scanline_timer->adjust(attotime::never); + return; + } + LOG2674(("width %u height %u max_x %u max_y %u refresh %f\n", horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, 1 / ATTOSECONDS_TO_DOUBLE(refresh))); rectangle visarea; @@ -594,22 +618,11 @@ void scn2674_device::device_timer(emu_timer &timer, device_timer_id id, int para m_display_enabled_scanline = 0; m_display_enabled_field = 0; } - else if(!m_display_enabled) - break; else m_linecounter++; - // should be triggered at the start of each ROW (line zero for that row) if(m_linecounter >= m_screen->height()) { - m_status_register |= 0x08; - if (m_irq_mask & 0x08) - { - LOG2674(("SCN2674 Line Zero\n")); - m_irq_state = 1; - m_irq_register |= 0x08; - m_irq_cb(1); - } m_linecounter = 0; m_address = (m_screen1_h << 8) | m_screen1_l; } @@ -629,6 +642,22 @@ void scn2674_device::device_timer(emu_timer &timer, device_timer_id id, int para if(m_linecounter >= (m_IR4_rows_per_screen * m_IR0_scanline_per_char_row)) break; + int charrow = m_linecounter % m_IR0_scanline_per_char_row; + int tilerow = charrow; + + // should be triggered at the start of each ROW (line zero for that row) + if(!charrow) + { + m_status_register |= 0x08; + if (m_irq_mask & 0x08) + { + LOG2674(("SCN2674 Line Zero\n")); + m_irq_state = 1; + m_irq_register |= 0x08; + m_irq_cb(1); + } + } + if((m_linecounter == (m_IR12_split_register_1 * m_IR0_scanline_per_char_row)) && m_linecounter) /* Split Screen 1 */ { m_status_register |= 0x04; @@ -661,8 +690,8 @@ void scn2674_device::device_timer(emu_timer &timer, device_timer_id id, int para dw = m_IR14_double_2; } - int charrow = m_linecounter % m_IR0_scanline_per_char_row; - int tilerow = charrow; + if(!m_display_enabled) + break; if(m_IR2_row_table) { @@ -684,7 +713,11 @@ void scn2674_device::device_timer(emu_timer &timer, device_timer_id id, int para m_screen2_h = (addr >> 8) & 0x3f; m_screen2_l = addr & 0xff; } - + } + else if(m_start1change && (m_start1change == (m_linecounter / m_IR0_scanline_per_char_row))) + { + m_address = (m_screen1_h << 8) | m_screen1_l; + m_start1change = 0; } if(dw == 2) diff --git a/src/emu/video/scn2674.h b/src/emu/video/scn2674.h index 2b1eaa17184..b30c65c4039 100644 --- a/src/emu/video/scn2674.h +++ b/src/emu/video/scn2674.h @@ -37,6 +37,8 @@ public: DECLARE_READ8_MEMBER( read ); DECLARE_WRITE8_MEMBER( write ); + DECLARE_READ8_MEMBER( buffer_r ) { return m_buffer; } + DECLARE_WRITE8_MEMBER( buffer_w ) { m_buffer = data; } UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_0) ? &m_space_config : NULL; } @@ -105,8 +107,10 @@ private: UINT8 m_spl1; UINT8 m_spl2; UINT8 m_dbl1; + UINT8 m_buffer; int m_linecounter; UINT16 m_address; + int m_start1change; UINT8 m_irq_state; diff --git a/src/mess/drivers/pcd.c b/src/mess/drivers/pcd.c index 8d53ff2ae7a..4b989d4b07d 100644 --- a/src/mess/drivers/pcd.c +++ b/src/mess/drivers/pcd.c @@ -17,9 +17,8 @@ #include "machine/wd_fdc.h" #include "machine/mc146818.h" #include "machine/pcd_kbd.h" -#include "machine/terminal.h" +#include "video/pcd.h" #include "sound/speaker.h" -#include "video/scn2674.h" #include "formats/pc_dsk.h" #include "bus/scsi/omti5100.h" #include "bus/rs232/rs232.h" @@ -39,16 +38,10 @@ public: m_speaker(*this, "speaker"), m_fdc(*this, "fdc"), m_rtc(*this, "rtc"), - m_crtc(*this, "crtc"), - m_palette(*this, "palette"), - m_gfxdecode(*this, "gfxdecode"), m_scsi(*this, "scsi"), m_scsi_data_out(*this, "scsi_data_out"), m_scsi_data_in(*this, "scsi_data_in"), - m_terminal(*this, "terminal"), - m_ram(*this, "ram"), - m_vram(*this, "vram"), - m_charram(8*1024) + m_ram(*this, "ram") { } DECLARE_READ8_MEMBER( irq_callback ); @@ -63,24 +56,16 @@ public: DECLARE_WRITE8_MEMBER( stat_w ); DECLARE_READ8_MEMBER( led_r ); DECLARE_WRITE8_MEMBER( led_w ); - DECLARE_READ8_MEMBER( detect_r ); - DECLARE_WRITE8_MEMBER( detect_w ); DECLARE_READ16_MEMBER( dskctl_r ); DECLARE_WRITE16_MEMBER( dskctl_w ); - DECLARE_READ8_MEMBER( mcu_r ); - DECLARE_WRITE8_MEMBER( mcu_w ); + DECLARE_READ8_MEMBER( scsi_r ); DECLARE_WRITE8_MEMBER( scsi_w ); - DECLARE_WRITE8_MEMBER( vram_sw_w ); - DECLARE_WRITE16_MEMBER( vram_w ); DECLARE_READ16_MEMBER( mmu_r ); DECLARE_WRITE16_MEMBER( mmu_w ); DECLARE_READ16_MEMBER( mem_r ); DECLARE_WRITE16_MEMBER( mem_w ); - DECLARE_READ8_MEMBER( exp_r ); - DECLARE_WRITE8_MEMBER( exp_w ); - DECLARE_WRITE8_MEMBER( term_key_w ); - SCN2674_DRAW_CHARACTER_MEMBER(display_pixels); + DECLARE_FLOPPY_FORMATS( floppy_formats ); DECLARE_WRITE_LINE_MEMBER(write_scsi_bsy); DECLARE_WRITE_LINE_MEMBER(write_scsi_cd); @@ -101,17 +86,11 @@ private: required_device m_speaker; required_device m_fdc; required_device m_rtc; - required_device m_crtc; - required_device m_palette; - required_device m_gfxdecode; required_device m_scsi; required_device m_scsi_data_out; required_device m_scsi_data_in; - optional_device m_terminal; required_device m_ram; - required_shared_ptr m_vram; - dynamic_buffer m_charram; - UINT8 m_stat, m_led, m_vram_sw, m_term_key; + UINT8 m_stat, m_led; int m_msg, m_bsy, m_io, m_cd, m_req, m_rst; emu_timer *m_req_hack; UINT16 m_dskctl; @@ -128,19 +107,6 @@ private: // MACHINE EMULATION //************************************************************************** -static const gfx_layout pcd_charlayout = -{ - 8, 14, /* 8 x 14 characters */ - 512, /* 512 characters */ - 1, /* 1 bits per pixel */ - { 0 }, /* no bitplanes */ - /* x offsets */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, - /* y offsets */ - { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8 }, - 8*16 -}; - void pcd_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { // TODO: remove this hack @@ -150,7 +116,6 @@ void pcd_state::device_timer(emu_timer &timer, device_timer_id id, int param, vo void pcd_state::machine_start() { - m_gfxdecode->set_gfx(0, global_alloc(gfx_element(machine().device("palette"), pcd_charlayout, &m_charram[0], 0, 1, 0))); m_req_hack = timer_alloc(); save_item(NAME(m_mmu.ctl)); save_item(NAME(m_mmu.regs)); @@ -161,12 +126,13 @@ void pcd_state::machine_reset() m_stat = 0; m_led = 0; m_dskctl = 0; - m_vram_sw = 1; m_rst = 0; m_mmu.ctl = 0; m_mmu.sc = false; - m_mmu.type = ioport("mmu")->read(); - m_term_key = 0; + if(ioport("mmu")) + m_mmu.type = ioport("mmu")->read(); + else + m_mmu.type = 0; } READ8_MEMBER( pcd_state::irq_callback ) @@ -185,22 +151,6 @@ WRITE_LINE_MEMBER( pcd_state::i186_timer1_w ) m_speaker->level_w(state); } -WRITE16_MEMBER( pcd_state::vram_w ) -{ - if(m_vram_sw) - COMBINE_DATA(&m_vram[offset]); - else if(mem_mask & 0xff) - { - m_charram[offset & 0x1fff] = data; - m_gfxdecode->gfx(0)->mark_dirty(offset/16); - } -} - -WRITE8_MEMBER( pcd_state::vram_sw_w ) -{ - m_vram_sw = data & 1; -} - READ8_MEMBER( pcd_state::nmi_io_r ) { if(space.debugger_access()) @@ -242,24 +192,6 @@ WRITE8_MEMBER( pcd_state::stat_w ) m_stat &= ~data; } -READ8_MEMBER( pcd_state::detect_r ) -{ - return 0; -} - -WRITE8_MEMBER( pcd_state::detect_w ) -{ -} - -READ8_MEMBER( pcd_state::mcu_r ) -{ - return 0x20; -} - -WRITE8_MEMBER( pcd_state::mcu_w ) -{ -} - READ16_MEMBER( pcd_state::dskctl_r ) { return m_dskctl; @@ -337,25 +269,6 @@ WRITE16_MEMBER( pcd_state::mmu_w ) } } -SCN2674_DRAW_CHARACTER_MEMBER(pcd_state::display_pixels) -{ - if(lg) - { - UINT16 data = m_vram[address]; - data = (data >> 8) | (data << 8); - for(int i = 0; i < 16; i++) - bitmap.pix32(y, x + i) = m_palette->pen((data & (1 << (15 - i))) ? 1 : 0); - } - else - { - UINT8 data = m_charram[(m_vram[address] & 0xff) * 16 + linecount]; - if(cursor && blink) - data = 0xff; - for(int i = 0; i < 8; i++) - bitmap.pix32(y, x + i) = m_palette->pen((data & (1 << (7 - i))) ? 1 : 0); - } -} - READ8_MEMBER(pcd_state::scsi_r) { UINT8 ret = 0; @@ -495,63 +408,18 @@ READ16_MEMBER(pcd_state::mem_r) return ram[offset]; } -// The PC-X treats the graphics board as a serial port. Maybe the 8031 (instead of 8047) can -// write directly to the video ram and there's a char ROM instead of RAM? -READ8_MEMBER(pcd_state::exp_r) -{ - if(m_dskctl & 0x40) - { - if(!offset) - { - UINT8 data = m_term_key; - m_term_key = 0; - return data; - } - else - { - m_pic2->ir0_w(CLEAR_LINE); - return (m_term_key ? 1 : 0); - } - } - else if(offset & 1) - return m_crtc->read(space, offset/2); - return 0xff; -} - -WRITE8_MEMBER(pcd_state::exp_w) -{ - if(m_dskctl & 0x40) - { - if(!offset) - { - m_pic2->ir0_w(ASSERT_LINE); - m_terminal->write(space, 0, data); - } - } - else if(!(offset & 1)) - return m_crtc->write(space, offset/2, data); -} - -WRITE8_MEMBER(pcd_state::term_key_w) -{ - m_pic2->ir0_w(ASSERT_LINE); - m_term_key = data; -} - //************************************************************************** // ADDRESS MAPS //************************************************************************** static ADDRESS_MAP_START( pcd_map, AS_PROGRAM, 16, pcd_state ) AM_RANGE(0x00000, 0x7ffff) AM_READWRITE(mem_r, mem_w) - AM_RANGE(0xf0000, 0xf7fff) AM_READONLY AM_WRITE(vram_w) AM_SHARE("vram") AM_RANGE(0xfc000, 0xfffff) AM_ROM AM_REGION("bios", 0) AM_RANGE(0x00000, 0xfffff) AM_READWRITE8(nmi_io_r, nmi_io_w, 0xffff) ADDRESS_MAP_END static ADDRESS_MAP_START( pcd_io, AS_IO, 16, pcd_state ) ADDRESS_MAP_UNMAP_HIGH - AM_RANGE(0x8000, 0x8fff) AM_READWRITE(mmu_r, mmu_w) AM_RANGE(0x0000, 0xefff) AM_READWRITE8(nmi_io_r, nmi_io_w, 0xffff) AM_RANGE(0xf000, 0xf7ff) AM_RAM AM_SHARE("nvram") AM_RANGE(0xf800, 0xf801) AM_DEVREADWRITE8("pic1", pic8259_device, read, write, 0xffff) @@ -562,21 +430,18 @@ static ADDRESS_MAP_START( pcd_io, AS_IO, 16, pcd_state ) AM_RANGE(0xf900, 0xf903) AM_DEVREADWRITE8("fdc", wd2793_t, read, write, 0xffff) AM_RANGE(0xf904, 0xf905) AM_READWRITE(dskctl_r, dskctl_w) AM_RANGE(0xf940, 0xf943) AM_READWRITE8(scsi_r, scsi_w, 0xffff) - AM_RANGE(0xf980, 0xf98f) AM_DEVWRITE8("crtc", scn2674_device, write, 0x00ff) - AM_RANGE(0xf980, 0xf98f) AM_DEVREAD8("crtc", scn2674_device, read, 0xff00) - AM_RANGE(0xf9a0, 0xf9a1) AM_WRITE8(vram_sw_w, 0x00ff) - AM_RANGE(0xf9b0, 0xf9b3) AM_READWRITE8(mcu_r, mcu_w, 0x00ff) // 8741 comms + AM_RANGE(0xf980, 0xf98f) AM_DEVICE("video", pcdx_video_device, map) AM_RANGE(0xf9c0, 0xf9c3) AM_DEVREADWRITE8("usart1",mc2661_device,read,write,0xffff) // UARTs AM_RANGE(0xf9d0, 0xf9d3) AM_DEVREADWRITE8("usart2",mc2661_device,read,write,0xffff) AM_RANGE(0xf9e0, 0xf9e3) AM_DEVREADWRITE8("usart3",mc2661_device,read,write,0xffff) // AM_RANGE(0xfa00, 0xfa7f) // pcs4-n (peripheral chip select) - AM_RANGE(0xfb00, 0xfb01) AM_READWRITE8(detect_r, detect_w, 0xff00) // expansion card detection? AM_RANGE(0xfb00, 0xffff) AM_READWRITE8(nmi_io_r, nmi_io_w, 0xffff) ADDRESS_MAP_END static ADDRESS_MAP_START( pcx_io, AS_IO, 16, pcd_state ) ADDRESS_MAP_UNMAP_HIGH - AM_RANGE(0xf980, 0xf98f) AM_READWRITE8(exp_r, exp_w, 0xffff) + AM_RANGE(0x8000, 0x8fff) AM_READWRITE(mmu_r, mmu_w) + AM_RANGE(0xfb00, 0xfb01) AM_READWRITE8(nmi_io_r, nmi_io_w, 0xff00) AM_IMPORT_FROM(pcd_io) ADDRESS_MAP_END @@ -593,7 +458,7 @@ FLOPPY_FORMATS_MEMBER( pcd_state::floppy_formats ) FLOPPY_PC_FORMAT FLOPPY_FORMATS_END -static INPUT_PORTS_START(pcd) +static INPUT_PORTS_START(pcx) PORT_START("mmu") PORT_CONFNAME(0x03, 0x00, "MMU Type") PORT_CONFSETTING(0x00, "None") @@ -608,14 +473,13 @@ static MACHINE_CONFIG_START( pcd, pcd_state ) MCFG_80186_TMROUT1_HANDLER(WRITELINE(pcd_state, i186_timer1_w)) MCFG_80186_IRQ_SLAVE_ACK(READ8(pcd_state, irq_callback)) - MCFG_CPU_ADD("graphics", I8741, XTAL_16MHz/2) - MCFG_DEVICE_DISABLE() - MCFG_TIMER_DRIVER_ADD_PERIODIC("timer0_tick", pcd_state, timer0_tick, attotime::from_hz(XTAL_16MHz / 24)) // adjusted to pass post MCFG_PIC8259_ADD("pic1", DEVWRITELINE("maincpu", i80186_cpu_device, int0_w), VCC, NULL) MCFG_PIC8259_ADD("pic2", DEVWRITELINE("maincpu", i80186_cpu_device, int1_w), VCC, NULL) + MCFG_DEVICE_ADD("video", PCD_VIDEO, 0) + MCFG_RAM_ADD(RAM_TAG) MCFG_RAM_DEFAULT_SIZE("1M") @@ -656,22 +520,6 @@ static MACHINE_CONFIG_START( pcd, pcd_state ) MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) - // video hardware - MCFG_SCREEN_ADD("screen", RASTER) - MCFG_SCREEN_SIZE(640, 350) - MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 349) - MCFG_SCREEN_REFRESH_RATE(50) - MCFG_SCREEN_UPDATE_DEVICE("crtc", scn2674_device, screen_update) - - MCFG_GFXDECODE_ADD("gfxdecode", "palette", empty) - MCFG_PALETTE_ADD_BLACK_AND_WHITE("palette") - - MCFG_SCN2674_VIDEO_ADD("crtc", 0, NULL); - MCFG_SCN2674_TEXT_CHARACTER_WIDTH(8) - MCFG_SCN2674_GFX_CHARACTER_WIDTH(16) - MCFG_SCN2674_DRAW_CHARACTER_CALLBACK_OWNER(pcd_state, display_pixels) - MCFG_VIDEO_SET_SCREEN("screen") - // rtc MCFG_MC146818_ADD("rtc", XTAL_32_768kHz) MCFG_MC146818_IRQ_HANDLER(DEVWRITELINE("pic1", pic8259_device, ir7_w)) @@ -696,11 +544,14 @@ MACHINE_CONFIG_DERIVED(pcx, pcd) MCFG_CPU_MODIFY("maincpu") MCFG_CPU_IO_MAP(pcx_io) - // FIXME: temporary workaround - MCFG_DEVICE_ADD("terminal", GENERIC_TERMINAL, 0) - MCFG_GENERIC_TERMINAL_KEYBOARD_CB(WRITE8(pcd_state, term_key_w)) + MCFG_DEVICE_REPLACE("video", PCX_VIDEO, 0) + MCFG_PCX_VIDEO_TXD_HANDLER(DEVWRITELINE("keyboard", pcd_keyboard_device, t0_w)) - MCFG_DEVICE_REMOVE("graphics") + MCFG_DEVICE_MODIFY("keyboard") + MCFG_PCD_KEYBOARD_OUT_TX_HANDLER(DEVWRITELINE("video", pcx_video_device, rx_w)) + + MCFG_DEVICE_MODIFY("usart2") + MCFG_MC2661_TXD_HANDLER(NULL) MACHINE_CONFIG_END //************************************************************************** @@ -715,10 +566,6 @@ ROM_START( pcd ) ROM_SYSTEM_BIOS(1, "v3", "V3 GS4") // from mainboard SYBAC S26361-D359 V3 GS4 ROMX_LOAD("361d0359.d42", 0x0001, 0x2000, CRC(5b4461e4) SHA1(db6756aeabb2e6d3921dc7571a5bed3497b964bf), ROM_SKIP(1) | ROM_BIOS(2)) ROMX_LOAD("361d0359.d43", 0x0000, 0x2000, CRC(71c3189d) SHA1(e8dd6c632bfc833074d3a833ea7f59bb5460f313), ROM_SKIP(1) | ROM_BIOS(2)) - - // gfx card (scn2674 with 8741), to be moved - ROM_REGION(0x400, "graphics", 0) - ROM_LOAD("s36361-d321-v1.bin", 0x000, 0x400, CRC(69baeb2a) SHA1(98b9cd0f38c51b4988a3aed0efcf004bedd115ff)) ROM_END ROM_START( pcx ) @@ -735,5 +582,5 @@ ROM_END // GAME DRIVERS //************************************************************************** -COMP( 1984, pcd, 0, 0, pcd, pcd, driver_device, 0, "Siemens", "PC-D", MACHINE_NOT_WORKING ) -COMP( 1984, pcx, pcd, 0, pcx, pcd, driver_device, 0, "Siemens", "PC-X", MACHINE_NOT_WORKING ) +COMP( 1984, pcd, 0, 0, pcd, 0, driver_device, 0, "Siemens", "PC-D", MACHINE_NOT_WORKING ) +COMP( 1984, pcx, pcd, 0, pcx, pcx, driver_device, 0, "Siemens", "PC-X", MACHINE_NOT_WORKING ) diff --git a/src/mess/machine/pcd_kbd.c b/src/mess/machine/pcd_kbd.c index 83618069458..e7825bb738b 100644 --- a/src/mess/machine/pcd_kbd.c +++ b/src/mess/machine/pcd_kbd.c @@ -7,6 +7,8 @@ const device_type PCD_KEYBOARD = &device_creator; ROM_START( pcd_keyboard ) ROM_REGION(0x1000, "mcu", 0) ROM_LOAD("pcd_keyboard.bin", 0x0000, 0x1000, CRC(d227d6cb) SHA1(3d6140764d3d043428c941826370ebf1597c63bd)) + ROM_FILL(0x526,1,0x03) // make the PCX video happy, TODO: figure out what's really happening + ROM_FILL(0x1e1,1,0x50) // fix csum ROM_END diff --git a/src/mess/video/pcd.c b/src/mess/video/pcd.c new file mode 100644 index 00000000000..3979f663a40 --- /dev/null +++ b/src/mess/video/pcd.c @@ -0,0 +1,373 @@ +// license:BSD-3-Clause +// copyright-holders:Carl + +#include "pcd.h" +#include "cpu/mcs51/mcs51.h" +#include "cpu/mcs48/mcs48.h" + +const device_type PCD_VIDEO = &device_creator; +const device_type PCX_VIDEO = &device_creator; + +pcdx_video_device::pcdx_video_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : + device_t(mconfig, type, name, tag, owner, clock, shortname, source), + m_maincpu(*this, ":maincpu"), + m_mcu(*this, "graphics"), + m_crtc(*this, "crtc"), + m_palette(*this, "palette"), + m_gfxdecode(*this, "gfxdecode") +{ +} + +pcd_video_device::pcd_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + pcdx_video_device(mconfig, PCD_VIDEO, "Siemens PC-D Video", tag, owner, clock, "pcd_video", __FILE__), + m_vram(32*1024), + m_charram(8*1024) +{ +} + +pcx_video_device::pcx_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + pcdx_video_device(mconfig, PCX_VIDEO, "Siemens PC-X Video", tag, owner, clock, "pcx_video", __FILE__), + device_serial_interface(mconfig, *this), + m_vram(4*1024), + m_charrom(*this, "char"), + m_pic2(*this, ":pic2"), + m_txd_handler(*this) +{ +} + +ROM_START( pcd_video ) + ROM_REGION(0x400, "graphics", 0) + ROM_LOAD("s36361-d321-v1.bin", 0x000, 0x400, CRC(69baeb2a) SHA1(98b9cd0f38c51b4988a3aed0efcf004bedd115ff)) +ROM_END + +const rom_entry *pcd_video_device::device_rom_region() const +{ + return ROM_NAME( pcd_video ); +} + +ROM_START( pcx_video ) + ROM_REGION(0x2000, "char", 0) + ROM_LOAD("d12-graka.bin", 0x0000, 0x2000, CRC(e4933c16) SHA1(932ae1f0cd2b029b7f5fc3d2d1679e70b25c0828)) + + ROM_REGION(0x6000, "graphics", 0) + ROM_LOAD("d40-graka.bin", 0x0000, 0x2000, CRC(dce48252) SHA1(0d9a575b2d001168a36864d7bd5db1c3aca5fb8d)) + ROM_LOAD("d39-graka.bin", 0x4000, 0x2000, CRC(02920e25) SHA1(145a6648d75c1dc4788f9bc7790281ef7e8f8426)) +ROM_END + +const rom_entry *pcx_video_device::device_rom_region() const +{ + return ROM_NAME( pcx_video ); +} + +static const gfx_layout pcd_charlayout = +{ + 8, 14, /* 8 x 14 characters */ + 512, /* 512 characters */ + 1, /* 1 bits per pixel */ + { 0 }, /* no bitplanes */ + /* x offsets */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, + /* y offsets */ + { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8 }, + 8*16 +}; + +static GFXDECODE_START( pcx ) + GFXDECODE_ENTRY( "char", 0x0000, pcd_charlayout, 0, 1 ) +GFXDECODE_END + +static MACHINE_CONFIG_FRAGMENT( pcd_video ) + MCFG_CPU_ADD("graphics", I8741, XTAL_16MHz/2) + MCFG_DEVICE_DISABLE() + + // video hardware + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_SIZE(640, 350) + MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 349) + MCFG_SCREEN_REFRESH_RATE(50) + MCFG_SCREEN_UPDATE_DEVICE("crtc", scn2674_device, screen_update) + + MCFG_GFXDECODE_ADD("gfxdecode", "palette", empty) + MCFG_PALETTE_ADD_BLACK_AND_WHITE("palette") + + MCFG_SCN2674_VIDEO_ADD("crtc", 0, NULL); + MCFG_SCN2674_TEXT_CHARACTER_WIDTH(8) + MCFG_SCN2674_GFX_CHARACTER_WIDTH(16) + MCFG_SCN2674_DRAW_CHARACTER_CALLBACK_OWNER(pcd_video_device, display_pixels) + MCFG_VIDEO_SET_SCREEN("screen") +MACHINE_CONFIG_END + +machine_config_constructor pcd_video_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( pcd_video ); +} + +static ADDRESS_MAP_START( pcx_vid_map, AS_PROGRAM, 8, pcx_video_device ) + AM_RANGE(0x0000, 0x5fff) AM_ROM AM_REGION("graphics", 0) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( pcx_vid_io, AS_IO, 8, pcx_video_device ) + AM_RANGE(0x8000, 0x8007) AM_DEVREADWRITE("crtc", scn2674_device, read, write) + AM_RANGE(0x8008, 0x8008) AM_READ(unk_r) + AM_RANGE(0xa000, 0xa001) AM_READWRITE(vram_latch_r, vram_latch_w) + AM_RANGE(0xa002, 0xa003) AM_READWRITE(term_mcu_r, term_mcu_w) + AM_RANGE(0xc000, 0xc7ff) AM_RAM +ADDRESS_MAP_END + +static ADDRESS_MAP_START( pcx_vram, AS_0, 8, pcx_video_device ) + AM_RANGE(0x0000, 0x07ff) AM_READWRITE(vram_r, vram_w) +ADDRESS_MAP_END + +static MACHINE_CONFIG_FRAGMENT( pcx_video ) + MCFG_CPU_ADD("graphics", I8031, XTAL_24MHz/2) + MCFG_CPU_PROGRAM_MAP(pcx_vid_map) + MCFG_CPU_IO_MAP(pcx_vid_io) + + // video hardware + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_SIZE(640, 350) + MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 349) + MCFG_SCREEN_REFRESH_RATE(50) + MCFG_SCREEN_UPDATE_DEVICE("crtc", scn2674_device, screen_update) + + MCFG_GFXDECODE_ADD("gfxdecode", "palette", pcx) + MCFG_PALETTE_ADD_BLACK_AND_WHITE("palette") + + MCFG_SCN2674_VIDEO_ADD("crtc", 0, INPUTLINE("graphics", MCS51_INT0_LINE)); + MCFG_SCN2674_TEXT_CHARACTER_WIDTH(8) + MCFG_SCN2674_GFX_CHARACTER_WIDTH(16) + MCFG_SCN2674_DRAW_CHARACTER_CALLBACK_OWNER(pcx_video_device, display_pixels) + MCFG_VIDEO_SET_SCREEN("screen") + MCFG_DEVICE_ADDRESS_MAP(AS_0, pcx_vram) +MACHINE_CONFIG_END + +machine_config_constructor pcx_video_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( pcx_video ); +} + +SCN2674_DRAW_CHARACTER_MEMBER(pcd_video_device::display_pixels) +{ + address <<= 1; + if(lg) + { + UINT16 data = m_vram[address + 1] | (m_vram[address] << 8); + for(int i = 0; i < 16; i++) + bitmap.pix32(y, x + i) = m_palette->pen((data & (1 << (15 - i))) ? 1 : 0); + } + else + { + UINT8 data; + data = m_charram[m_vram[address] * 16 + linecount]; + if(cursor && blink) + data = 0xff; + for(int i = 0; i < 8; i++) + bitmap.pix32(y, x + i) = m_palette->pen((data & (1 << (7 - i))) ? 1 : 0); + } +} + +SCN2674_DRAW_CHARACTER_MEMBER(pcx_video_device::display_pixels) +{ + UINT8 data; + address <<= 1; + data = m_charrom[m_vram[address] * 16 + linecount + (m_vram[address + 1] & 0x20 ? 4096 : 0)]; + if(cursor && blink) + data = 0xff; + for(int i = 0; i < 8; i++) + bitmap.pix32(y, x + i) = m_palette->pen((data & (1 << (7 - i))) ? 1 : 0); +} + +WRITE8_MEMBER(pcd_video_device::vram_w) +{ + if(m_vram_sw) + m_vram[offset] = data; + else if(!(offset & 1)) + { + offset >>= 1; + m_charram[offset & 0x1fff] = data; + m_gfxdecode->gfx(0)->mark_dirty(offset/16); + } +} + +READ8_MEMBER(pcd_video_device::vram_r) +{ + return m_vram[offset]; +} + +WRITE8_MEMBER(pcd_video_device::vram_sw_w) +{ + m_vram_sw = data & 1; +} + + +READ8_MEMBER(pcd_video_device::mcu_r) +{ + return 0x20; +} + +WRITE8_MEMBER(pcd_video_device::mcu_w) +{ +} + +READ8_MEMBER(pcx_video_device::term_r) +{ + switch(offset) + { + case 0: + m_pic2->ir0_w(CLEAR_LINE); + m_term_stat &= ~2; + return m_term_key; + case 1: + m_pic2->ir0_w(CLEAR_LINE); + return m_term_stat >> 1; + } + return 0xff; +} + +WRITE8_MEMBER(pcx_video_device::term_w) +{ + if(!offset) + { + m_mcu->set_input_line(MCS51_INT1_LINE, ASSERT_LINE); + m_term_char = data; + m_term_stat |= 4; + } +} + +READ8_MEMBER(pcx_video_device::term_mcu_r) +{ + switch(offset) + { + case 0: + m_mcu->set_input_line(MCS51_INT1_LINE, CLEAR_LINE); + m_pic2->ir0_w(ASSERT_LINE); + m_term_stat &= ~4; + return m_term_char; + case 1: + return m_term_stat; + } + return 0; +} + +WRITE8_MEMBER(pcx_video_device::term_mcu_w) +{ + if(!offset) + { + m_term_key = data; + m_pic2->ir0_w(ASSERT_LINE); + m_term_stat |= 2; + } +} + +WRITE8_MEMBER(pcx_video_device::vram_w) +{ + offset <<= 1; + m_vram[offset] = m_vram_latch_w[0]; + m_vram[offset+1] = m_vram_latch_w[1]; +} + +READ8_MEMBER(pcx_video_device::vram_r) +{ + offset <<= 1; + m_vram_latch_r[0] = m_vram[offset]; + m_vram_latch_r[1] = m_vram[offset+1]; + return m_vram[offset]; +} + +WRITE8_MEMBER(pcx_video_device::vram_latch_w) +{ + m_vram_latch_w[offset] = data; +} + +READ8_MEMBER(pcx_video_device::vram_latch_r) +{ + return m_vram_latch_r[offset]; +} + +READ8_MEMBER(pcdx_video_device::detect_r) +{ + return 0; +} + +WRITE8_MEMBER(pcdx_video_device::detect_w) +{ +} + +READ8_MEMBER(pcx_video_device::unk_r) +{ + return 0x80; +} + +void pcd_video_device::device_start() +{ + m_maincpu->space(AS_IO).install_write_handler(0xf9a0, 0xf9a1, 0, 0, write8_delegate(FUNC(pcd_video_device::vram_sw_w), this), 0x00ff); + m_maincpu->space(AS_IO).install_readwrite_handler(0xf9b0, 0xf9b3, 0, 0, read8_delegate(FUNC(pcd_video_device::mcu_r), this), write8_delegate(FUNC(pcd_video_device::mcu_w), this), 0x00ff); + m_maincpu->space(AS_IO).install_readwrite_handler(0xfb00, 0xfb01, 0, 0, read8_delegate(FUNC(pcdx_video_device::detect_r), this), write8_delegate(FUNC(pcdx_video_device::detect_w), this), 0xff00); + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xf0000, 0xf7fff, 0, 0, read8_delegate(FUNC(pcd_video_device::vram_r), this), write8_delegate(FUNC(pcd_video_device::vram_w), this), 0xffff); + m_gfxdecode->set_gfx(0, global_alloc(gfx_element(machine().device("palette"), pcd_charlayout, &m_charram[0], 0, 1, 0))); +} + +void pcd_video_device::device_reset() +{ + m_vram_sw = 1; +} + + +DEVICE_ADDRESS_MAP_START(map, 16, pcd_video_device) + AM_RANGE(0x0, 0xf) AM_DEVWRITE8("crtc", scn2674_device, write, 0x00ff) + AM_RANGE(0x0, 0xf) AM_DEVREAD8("crtc", scn2674_device, read, 0xff00) +ADDRESS_MAP_END + +void pcx_video_device::device_start() +{ + mcs51_cpu_device *mcu = downcast(m_mcu.target()); + m_maincpu->space(AS_IO).install_readwrite_handler(0xfb00, 0xfb01, 0, 0, read8_delegate(FUNC(pcdx_video_device::detect_r), this), write8_delegate(FUNC(pcdx_video_device::detect_w), this), 0x00ff); + m_txd_handler.resolve_safe(); + + // set serial callbacks + mcu->i8051_set_serial_tx_callback(WRITE8_DELEGATE(pcx_video_device, tx_callback)); + mcu->i8051_set_serial_rx_callback(READ8_DELEGATE(pcx_video_device, rx_callback)); + set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1); + set_rate(600*2); // FIXME: fix the keyboard when the mc2661 baud rate calc is fixed +} + +void pcx_video_device::device_reset() +{ + m_term_key = 0; + m_term_stat = 0; + transmit_register_reset(); + receive_register_reset(); + + m_txd_handler(1); +} + +DEVICE_ADDRESS_MAP_START(map, 16, pcx_video_device) + AM_RANGE(0x0, 0xf) AM_READWRITE8(term_r, term_w, 0xffff) +ADDRESS_MAP_END + +READ8_MEMBER(pcx_video_device::rx_callback) +{ + return get_received_char(); +} + +WRITE8_MEMBER(pcx_video_device::tx_callback) +{ + transmit_register_setup(data); +} + +void pcx_video_device::tra_callback() +{ + m_txd_handler(transmit_register_get_data_bit()); +} + +void pcx_video_device::rcv_complete() +{ + receive_register_extract(); + m_mcu->set_input_line(MCS51_RX_LINE, ASSERT_LINE); + m_mcu->set_input_line(MCS51_RX_LINE, CLEAR_LINE); +} + +void pcx_video_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + device_serial_interface::device_timer(timer, id, param, ptr); +} diff --git a/src/mess/video/pcd.h b/src/mess/video/pcd.h new file mode 100644 index 00000000000..dabd206b9d2 --- /dev/null +++ b/src/mess/video/pcd.h @@ -0,0 +1,95 @@ +// license:BSD-3-Clause +// copyright-holders:Carl + +#ifndef _PCD_H_ +#define _PCD_H_ + +#include "emu.h" +#include "machine/pic8259.h" +#include "video/scn2674.h" + +#define MCFG_PCX_VIDEO_TXD_HANDLER(_devcb) \ + devcb = &pcx_video_device::set_txd_handler(*device, DEVCB_##_devcb); + +class pcdx_video_device : public device_t +{ +public: + pcdx_video_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + + virtual DECLARE_ADDRESS_MAP(map, 16) = 0; + DECLARE_READ8_MEMBER(detect_r); + DECLARE_WRITE8_MEMBER(detect_w); +protected: + required_device m_maincpu; + required_device m_mcu; + required_device m_crtc; + required_device m_palette; + required_device m_gfxdecode; +}; + +class pcd_video_device : public pcdx_video_device +{ +public: + pcd_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + DECLARE_ADDRESS_MAP(map, 16); + DECLARE_ADDRESS_MAP(vram_map, 8); + DECLARE_READ8_MEMBER(mcu_r); + DECLARE_WRITE8_MEMBER(mcu_w); + DECLARE_WRITE8_MEMBER(vram_sw_w); + DECLARE_READ8_MEMBER(vram_r); + DECLARE_WRITE8_MEMBER(vram_w); + + virtual const rom_entry *device_rom_region() const; + virtual machine_config_constructor device_mconfig_additions() const; + SCN2674_DRAW_CHARACTER_MEMBER(display_pixels); +protected: + void device_start(); + void device_reset(); +private: + dynamic_buffer m_vram; + dynamic_buffer m_charram; + UINT8 m_vram_sw; +}; + +class pcx_video_device : public pcdx_video_device, + public device_serial_interface +{ +public: + pcx_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + template static devcb_base &set_txd_handler(device_t &device, _Object object) { return downcast(device).m_txd_handler.set_callback(object); } + + DECLARE_ADDRESS_MAP(map, 16); + DECLARE_READ8_MEMBER(term_r); + DECLARE_WRITE8_MEMBER(term_w); + DECLARE_READ8_MEMBER(term_mcu_r); + DECLARE_WRITE8_MEMBER(term_mcu_w); + DECLARE_READ8_MEMBER(rx_callback); + DECLARE_WRITE8_MEMBER(tx_callback); + DECLARE_READ8_MEMBER(vram_r); + DECLARE_WRITE8_MEMBER(vram_w); + DECLARE_READ8_MEMBER(vram_latch_r); + DECLARE_WRITE8_MEMBER(vram_latch_w); + DECLARE_READ8_MEMBER(unk_r); + + virtual const rom_entry *device_rom_region() const; + virtual machine_config_constructor device_mconfig_additions() const; + SCN2674_DRAW_CHARACTER_MEMBER(display_pixels); +protected: + void device_start(); + void device_reset(); + void tra_callback(); + void rcv_complete(); + void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); +private: + dynamic_buffer m_vram; + required_region_ptr m_charrom; + required_device m_pic2; + devcb_write_line m_txd_handler; + UINT8 m_term_key, m_term_char, m_term_stat, m_vram_latch_r[2], m_vram_latch_w[2]; +}; + +extern const device_type PCD_VIDEO; +extern const device_type PCX_VIDEO; + +#endif