diff --git a/src/devices/video/tms9927.cpp b/src/devices/video/tms9927.cpp index b0553642316..3c36f644c69 100644 --- a/src/devices/video/tms9927.cpp +++ b/src/devices/video/tms9927.cpp @@ -16,8 +16,8 @@ static const uint8_t skew_bits_value[4] = { 0, 1, 2, 2 }; #define HCOUNT (m_reg[0] + 1) #define INTERLACED ((m_reg[1] >> 7) & 0x01) -#define HSYNC_WIDTH ((m_reg[1] >> 4) & 0x0f) -#define HSYNC_DELAY ((m_reg[1] >> 0) & 0x07) +#define HSYNC_WIDTH (((m_reg[1] >> 3) & 0x0f) + 1) +#define HSYNC_DELAY (((m_reg[1] >> 0) & 0x07) + 1) #define SCANS_PER_DATA_ROW (((m_reg[2] >> 3) & 0x0f) + 1) #define CHARS_PER_DATA_ROW (chars_per_row_value[(m_reg[2] >> 0) & 0x07]) #define SKEW_BITS (skew_bits_value[(m_reg[3] >> 6) & 0x03]) @@ -45,6 +45,10 @@ tms9927_device::tms9927_device(const machine_config &mconfig, device_type type, , device_video_interface(mconfig, *this) , m_write_vsyn(*this) , m_hpixels_per_column(0) + , m_overscan_left(0) + , m_overscan_right(0) + , m_overscan_top(0) + , m_overscan_bottom(0) , m_selfload(*this, finder_base::DUMMY_TAG) , m_reset(0) { @@ -108,7 +112,7 @@ void tms9927_device::device_reset() void tms9927_device::device_stop() { - osd_printf_debug("TMS9937: Final params: (%d, %d, %d, %d, %d, %d, %d)\n", + osd_printf_debug("TMS9927: Final params: (%d, %d, %d, %d, %d, %d, %d)\n", m_clock, m_total_hpix, 0, m_visible_hpix, @@ -194,7 +198,6 @@ void tms9927_device::generic_access(address_space &space, offs_t offset) } } - WRITE8_MEMBER( tms9927_device::write ) { switch (offset) @@ -270,8 +273,7 @@ int tms9927_device::cursor_bounds(rectangle &bounds) void tms9927_device::recompute_parameters(bool postload) { - uint16_t offset_hpix, offset_vpix; - attoseconds_t refresh; + attoseconds_t refresh; rectangle visarea; if (m_reset) @@ -286,11 +288,8 @@ void tms9927_device::recompute_parameters(bool postload) m_visible_vpix = DATA_ROWS_PER_FRAME * SCANS_PER_DATA_ROW; m_start_datarow = (LAST_DISP_DATA_ROW + 1) % DATA_ROWS_PER_FRAME; - /* determine the horizontal/vertical offsets */ - offset_hpix = HSYNC_DELAY * m_hpixels_per_column; - offset_vpix = VERTICAL_DATA_START; - osd_printf_debug("TMS9937: Total = %dx%d, Visible = %dx%d, Offset=%dx%d, Skew=%d, Upscroll=%d\n", m_total_hpix, m_total_vpix, m_visible_hpix, m_visible_vpix, offset_hpix, offset_vpix, SKEW_BITS, m_start_datarow); + osd_printf_debug("TMS9927: Total = %dx%d, Visible = %dx%d, Skew=%d, Upscroll=%d\n", m_total_hpix, m_total_vpix, m_visible_hpix, m_visible_vpix, SKEW_BITS, m_start_datarow); /* see if it all makes sense */ m_valid_config = true; @@ -310,10 +309,10 @@ void tms9927_device::recompute_parameters(bool postload) /* update */ if (!m_valid_config) return; - + /* create a visible area */ - /* fix me: how do the offsets fit in here? */ - visarea.set(0, m_visible_hpix - 1, 0, m_visible_vpix - 1); + visarea.set(0, m_overscan_left + m_visible_hpix + m_overscan_right - 1, + 0, m_overscan_top + m_visible_vpix + m_overscan_bottom - 1); refresh = HZ_TO_ATTOSECONDS(m_clock) * m_total_hpix * m_total_vpix; @@ -321,4 +320,5 @@ void tms9927_device::recompute_parameters(bool postload) m_vsyn = 0; m_vsync_timer->adjust(m_screen->time_until_pos(0, 0)); + } diff --git a/src/devices/video/tms9927.h b/src/devices/video/tms9927.h index eac4fdc8463..11a3648fbf8 100644 --- a/src/devices/video/tms9927.h +++ b/src/devices/video/tms9927.h @@ -19,7 +19,9 @@ #define MCFG_TMS9927_REGION(_tag) \ tms9927_device::set_region_tag(*device, "^" _tag); - +#define MCFG_TMS9927_OVERSCAN(_left, _right, _top, _bottom) \ + tms9927_device::set_overscan(*device, _left, _right, _top, _bottom); + class tms9927_device : public device_t, public device_video_interface { @@ -32,7 +34,14 @@ public: static void set_char_width(device_t &device, int pixels) { downcast(device).m_hpixels_per_column = pixels; } static void set_region_tag(device_t &device, const char *tag) { downcast(device).m_selfload.set_tag(tag); } - + static void set_overscan(device_t &device, int left, int right, int top, int bottom) { + tms9927_device &dev = downcast(device); + dev.m_overscan_left = left; + dev.m_overscan_right = right; + dev.m_overscan_top = top; + dev.m_overscan_bottom = bottom; + } + DECLARE_WRITE8_MEMBER(write); DECLARE_READ8_MEMBER(read); @@ -59,7 +68,11 @@ private: devcb_write_line m_write_vsyn; int m_hpixels_per_column; /* number of pixels per video memory address */ - + uint16_t m_overscan_left; + uint16_t m_overscan_right; + uint16_t m_overscan_top; + uint16_t m_overscan_bottom; + // internal state optional_region_ptr m_selfload; @@ -68,12 +81,13 @@ private: uint8_t m_reg[9]; uint8_t m_start_datarow; uint8_t m_reset; - + /* derived state; no need to save */ uint8_t m_valid_config; uint16_t m_total_hpix, m_total_vpix; uint16_t m_visible_hpix, m_visible_vpix; + int m_vsyn; emu_timer *m_vsync_timer; diff --git a/src/mame/drivers/intv.cpp b/src/mame/drivers/intv.cpp index c73695c5d33..d29ffaf0e59 100644 --- a/src/mame/drivers/intv.cpp +++ b/src/mame/drivers/intv.cpp @@ -53,6 +53,7 @@ RO-3-9506 = 8KiB (4Kiw) self decoding address mask rom with external address dec #include "emu.h" #include "cpu/m6502/m6502.h" #include "cpu/cp1610/cp1610.h" +#include "video/tms9927.h" #include "includes/intv.h" #include "sound/ay8910.h" #include "softlist.h" @@ -236,7 +237,7 @@ static INPUT_PORTS_START( intvkbd ) PORT_START("ROW7") PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('O') PORT_CHAR(')') + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('\xA2') PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') @@ -409,8 +410,10 @@ ADDRESS_MAP_END static ADDRESS_MAP_START( intvkbd2_mem , AS_PROGRAM, 8, intv_state ) ADDRESS_MAP_UNMAP_HIGH /* Required because of probing */ AM_RANGE(0x0000, 0x3fff) AM_READWRITE(intvkbd_dualport8_lsb_r, intvkbd_dualport8_lsb_w) /* Dual-port RAM */ - AM_RANGE(0x4000, 0x7fff) AM_READWRITE(intvkbd_dualport8_msb_r, intvkbd_dualport8_msb_w) /* Dual-port RAM */ - AM_RANGE(0xb7f8, 0xb7ff) AM_RAM /* ??? */ + AM_RANGE(0x4000, 0x40bf) AM_READWRITE(intvkbd_io_r, intvkbd_io_w) + AM_RANGE(0x40c0, 0x40cf) AM_DEVREADWRITE("crtc", tms9927_device, read, write) + AM_RANGE(0x4200, 0x7fff) AM_READWRITE(intvkbd_dualport8_msb_r, intvkbd_dualport8_msb_w) /* Dual-port RAM */ + AM_RANGE(0xb7f8, 0xb7ff) AM_READWRITE(intvkbd_periph_r, intvkbd_periph_w) AM_RANGE(0xb800, 0xbfff) AM_RAM AM_SHARE("videoram") /* Text Display */ AM_RANGE(0xc000, 0xdfff) AM_ROM AM_RANGE(0xe000, 0xffff) AM_READ(intvkb_iocart_r) @@ -538,9 +541,13 @@ static MACHINE_CONFIG_DERIVED( intvkbd, intv ) MCFG_PALETTE_MODIFY("palette") MCFG_PALETTE_INIT_OWNER(intv_state, intv) + /* crt controller */ + MCFG_DEVICE_ADD("crtc", TMS9927, XTAL_7_15909MHz) + MCFG_TMS9927_CHAR_WIDTH(8) + MCFG_TMS9927_OVERSCAN(STIC_OVERSCAN_LEFT_WIDTH*STIC_X_SCALE*INTVKBD_X_SCALE, STIC_OVERSCAN_RIGHT_WIDTH*STIC_X_SCALE*INTVKBD_X_SCALE, + STIC_OVERSCAN_TOP_HEIGHT*STIC_Y_SCALE*INTVKBD_Y_SCALE, STIC_OVERSCAN_BOTTOM_HEIGHT*STIC_Y_SCALE*INTVKBD_Y_SCALE) + MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_SIZE((STIC_OVERSCAN_LEFT_WIDTH+STIC_BACKTAB_WIDTH*STIC_CARD_WIDTH-1+STIC_OVERSCAN_RIGHT_WIDTH)*STIC_X_SCALE*INTVKBD_X_SCALE, (STIC_OVERSCAN_TOP_HEIGHT+STIC_BACKTAB_HEIGHT*STIC_CARD_HEIGHT+STIC_OVERSCAN_BOTTOM_HEIGHT)*STIC_Y_SCALE*INTVKBD_Y_SCALE) - MCFG_SCREEN_VISIBLE_AREA(0, (STIC_OVERSCAN_LEFT_WIDTH+STIC_BACKTAB_WIDTH*STIC_CARD_WIDTH-1+STIC_OVERSCAN_RIGHT_WIDTH)*STIC_X_SCALE*INTVKBD_X_SCALE-1, 0, (STIC_OVERSCAN_TOP_HEIGHT+STIC_BACKTAB_HEIGHT*STIC_CARD_HEIGHT+STIC_OVERSCAN_BOTTOM_HEIGHT)*STIC_Y_SCALE*INTVKBD_Y_SCALE-1) MCFG_SCREEN_UPDATE_DRIVER(intv_state, screen_update_intvkbd) /* I/O cartslots for BASIC */ diff --git a/src/mame/includes/intv.h b/src/mame/includes/intv.h index 0b5b9ffdbcd..b5f0c2a335a 100644 --- a/src/mame/includes/intv.h +++ b/src/mame/includes/intv.h @@ -38,6 +38,7 @@ public: m_maincpu(*this, "maincpu"), m_sound(*this, "ay8914"), m_stic(*this, "stic"), + m_crtc(*this, "crtc"), m_cart(*this, "cartslot"), m_intvkbd_dualport_ram(*this, "dualport_ram"), m_videoram(*this, "videoram"), @@ -54,6 +55,7 @@ public: required_device m_maincpu; required_device m_sound; required_device m_stic; + optional_device m_crtc; optional_device m_cart; optional_shared_ptr m_intvkbd_dualport_ram; optional_shared_ptr m_videoram; @@ -78,25 +80,26 @@ public: uint8_t m_ram8[256]; // Keyboard Component - DECLARE_READ8_MEMBER(intvkbd_tms9927_r); - DECLARE_WRITE8_MEMBER(intvkbd_tms9927_w); DECLARE_WRITE16_MEMBER(intvkbd_dualport16_w); DECLARE_READ8_MEMBER(intvkbd_dualport8_lsb_r); DECLARE_WRITE8_MEMBER(intvkbd_dualport8_lsb_w); DECLARE_READ8_MEMBER(intvkbd_dualport8_msb_r); DECLARE_WRITE8_MEMBER(intvkbd_dualport8_msb_w); + DECLARE_READ8_MEMBER(intvkbd_io_r); + DECLARE_WRITE8_MEMBER(intvkbd_io_w); + DECLARE_READ8_MEMBER(intvkbd_periph_r); + DECLARE_WRITE8_MEMBER(intvkbd_periph_w); - uint8_t m_tms9927_num_rows; - uint8_t m_tms9927_cursor_col; - uint8_t m_tms9927_cursor_row; - uint8_t m_tms9927_last_row; + bool m_printer_not_busy; // printer state + bool m_printer_no_paper; // printer state + bool m_printer_not_busy_enable; // printer interface state int m_intvkbd_text_blanked; int m_intvkbd_keyboard_col; int m_tape_int_pending; int m_tape_interrupts_enabled; - int m_tape_unknown_write[6]; int m_tape_motor_mode; + DECLARE_DRIVER_INIT(intvecs); DECLARE_DRIVER_INIT(intvkbd); DECLARE_DRIVER_INIT(intv); diff --git a/src/mame/machine/intv.cpp b/src/mame/machine/intv.cpp index 38498eccce1..594e9336049 100644 --- a/src/mame/machine/intv.cpp +++ b/src/mame/machine/intv.cpp @@ -2,10 +2,11 @@ // copyright-holders:Nathan Woods,Frank Palazzolo #include "emu.h" #include "video/stic.h" +#include "video/tms9927.h" #include "includes/intv.h" #include "cpu/cp1610/cp1610.h" - +// Dual Port Memory handlers WRITE16_MEMBER( intv_state::intvkbd_dualport16_w ) { @@ -35,215 +36,450 @@ WRITE8_MEMBER( intv_state::intvkbd_dualport8_lsb_w ) RAM[offset] = data; } - - READ8_MEMBER( intv_state::intvkbd_dualport8_msb_r ) { - unsigned char rv; - - if (offset < 0x100) - { - switch (offset) - { - case 0x000: - rv = m_io_test->read() & 0x80; - logerror("TAPE: Read %02x from 0x40%02x - XOR Data?\n",rv,offset); - break; - case 0x001: - rv = (m_io_test->read() & 0x40) << 1; - logerror("TAPE: Read %02x from 0x40%02x - Sense 1?\n",rv,offset); - break; - case 0x002: - rv = (m_io_test->read() & 0x20) << 2; - logerror("TAPE: Read %02x from 0x40%02x - Sense 2?\n",rv,offset); - break; - case 0x003: - rv = (m_io_test->read() & 0x10) << 3; - logerror("TAPE: Read %02x from 0x40%02x - Tape Present\n",rv,offset); - break; - case 0x004: - rv = (m_io_test->read() & 0x08) << 4; - logerror("TAPE: Read %02x from 0x40%02x - Comp (339/1)\n",rv,offset); - break; - case 0x005: - rv = (m_io_test->read() & 0x04) << 5; - logerror("TAPE: Read %02x from 0x40%02x - Clocked Comp (339/13)\n",rv,offset); - break; - case 0x006: - if (m_sr1_int_pending) - rv = 0x00; - else - rv = 0x80; - logerror("TAPE: Read %02x from 0x40%02x - SR1 Int Pending\n",rv,offset); - break; - case 0x007: - if (m_tape_int_pending) - rv = 0x00; - else - rv = 0x80; - logerror("TAPE: Read %02x from 0x40%02x - Tape? Int Pending\n",rv,offset); - break; - case 0x060: /* Keyboard Read */ - rv = 0xff; - if (m_intvkbd_keyboard_col < 10) - rv = m_intv_keyboard[m_intvkbd_keyboard_col]->read(); - break; - case 0x80: - rv = 0x00; - logerror("TAPE: Read %02x from 0x40%02x, clear tape int pending\n",rv,offset); - m_tape_int_pending = 0; - break; - case 0xa0: - rv = 0x00; - logerror("TAPE: Read %02x from 0x40%02x, clear SR1 int pending\n",rv,offset); - m_sr1_int_pending = 0; - break; - case 0xc0: - case 0xc1: - case 0xc2: - case 0xc3: - case 0xc4: - case 0xc5: - case 0xc6: - case 0xc7: - case 0xc8: - case 0xc9: - case 0xca: - case 0xcb: - case 0xcc: - case 0xcd: - case 0xce: - case 0xcf: - /* TMS9927 regs */ - rv = intvkbd_tms9927_r(space, offset-0xc0); - break; - default: - rv = (m_intvkbd_dualport_ram[offset]&0x0300)>>8; - logerror("Unknown read %02x from 0x40%02x\n",rv,offset); - break; - } - return rv; - } - else - return (m_intvkbd_dualport_ram[offset]&0x0300)>>8; + return (m_intvkbd_dualport_ram[offset+0x200]&0x0300)>>8; } -static const char *const tape_motor_mode_desc[8] = -{ - "IDLE", "IDLE", "IDLE", "IDLE", - "EJECT", "PLAY/RECORD", "REWIND", "FF" -}; - WRITE8_MEMBER( intv_state::intvkbd_dualport8_msb_w ) { - unsigned int mask; + unsigned int mask = m_intvkbd_dualport_ram[offset+0x200] & 0x00ff; + m_intvkbd_dualport_ram[offset+0x200] = mask | ((data<<8)&0x0300); +} - if (offset < 0x100) +// I/O for the Tape Drive +// (to be moved to a device) +struct tape_drive_state_type +{ + /* read state */ + int read_data; /* 0x4000 */ + int ready; /* 0x4001 */ + int leader_detect; /* 0x4002 */ + int tape_missing; /* 0x4003 */ + int playing; /* 0x4004 */ + int no_data; /* 0x4005 */ + + /* write state */ + int motor_state; /* 0x4020-0x4022 */ + int writing; /* 0x4023 */ + int audio_b_mute; /* 0x4024 */ + int audio_a_mute; /* 0x4025 */ + int channel_select; /* 0x4026 */ + int erase; /* 0x4027 */ + int write_data; /* 0x4040 */ + + /* bit_counter */ + int bit_counter; +} tape_drive; + +//static const char *const tape_motor_mode_desc[8] = +//{ +// "IDLE", "IDLE", "IDLE", "IDLE", +// "EJECT", "PLAY/RECORD", "REWIND", "FF" +//}; + + +READ8_MEMBER( intv_state::intvkbd_io_r ) +{ + unsigned char rv = 0x00; + + switch (offset) { - switch (offset) + // These next 8 locations all map to bit7 + case 0x000: + // "Data from Cassette" + // Tape drive does the decoding to bits + //rv = m_io_test->read() & 0x80; + rv = tape_drive.read_data << 7; + break; + case 0x001: + // "Watermark" + // 0 = Drive Busy Executing Command?, 1 = Drive Ok? + //rv = (m_io_test->read() & 0x40) << 1; + rv = tape_drive.ready << 7; + break; + case 0x002: + // "End of Tape" + // 0 = Recordable surface, 1 = Leader Detect + // (Leader is transparent, optical sensor) + //rv = (m_io_test->read() & 0x20) << 2; + rv = tape_drive.leader_detect << 7; + //logerror("TAPE: Read %02x from 0x40%02x - Sense 2?\n",rv,offset); + break; + case 0x003: + // "Cassette Present" + // 0 = Tape Present, 1 = Tape Not Present + //rv = (m_io_test->read() & 0x10) << 3; + rv = tape_drive.tape_missing << 7; + //logerror("TAPE: Read %02x from 0x40%02x - Tape Present\n",rv,offset); + break; + case 0x004: + // "NOT Inter Record Gap (IRG)" + // 0 = Not Playing/Recording?, 1 = Playing/Recording? + //rv = (m_io_test->read() & 0x08) << 4; + rv = tape_drive.playing << 7; + //logerror("TAPE: Read %02x from 0x40%02x - Comp (339/1)\n",rv,offset); + break; + case 0x005: + // "Dropout" + // 0 = Data Detect, 1 = No Data + //rv = (m_io_test->read() & 0x04) << 5; + rv = tape_drive.no_data << 7; + //logerror("TAPE: Read %02x from 0x40%02x - Clocked Comp (339/13)\n",rv,offset); + break; + case 0x006: + // "NOT Clock Interrupt" + if (m_sr1_int_pending) + rv = 0x00; + else + rv = 0x80; + //logerror("TAPE: Read %02x from 0x40%02x - SR1 Int Pending\n",rv,offset); + break; + case 0x007: + // "NOT Tape Interrupt" + if (m_tape_int_pending) + rv = 0x00; + else + rv = 0x80; + //logerror("TAPE: Read %02x from 0x40%02x - Tape? Int Pending\n",rv,offset); + break; + case 0x060: + // "Read Keyboard" + rv = 0xff; + if (m_intvkbd_keyboard_col < 10) + rv = m_intv_keyboard[m_intvkbd_keyboard_col]->read(); + break; + case 0x80: + // "Clear Tape Interrupt" + rv = 0x00; + //logerror("TAPE: Read %02x from 0x40%02x, clear tape int pending\n",rv,offset); + m_tape_int_pending = 0; + break; + case 0xa0: + // "Clear Clock Interrupt" + rv = 0x00; + //logerror("TAPE: Read %02x from 0x40%02x, clear SR1 int pending\n",rv,offset); + m_sr1_int_pending = 0; + break; + default: + //logerror("Unknown read %02x from 0x40%02x\n",rv,offset); + break; + } + return rv; +} + +WRITE8_MEMBER( intv_state::intvkbd_io_w ) +{ + switch (offset) + { + // Bits from offset $20 to $47 are all bit0, write only + // These are all set to zero by system reset + case 0x020: + // "Tape Drive Control: Enable" + tape_drive.motor_state &= 3; + if (data & 1) + tape_drive.motor_state |= 4; + //logerror("TAPE: Motor Mode: %s\n",tape_motor_mode_desc[m_tape_motor_mode]); + break; + case 0x021: + // "Tape Drive Control: Forward" + tape_drive.motor_state &= 5; + if (data & 1) + tape_drive.motor_state |= 2; + //logerror("TAPE: Motor Mode: %s\n",tape_motor_mode_desc[m_tape_motor_mode]); + break; + case 0x022: + // "Tape Drive Control: Fast" + tape_drive.motor_state &= 6; + if (data & 1) + tape_drive.motor_state |= 1; + //logerror("TAPE: Motor Mode: %s\n",tape_motor_mode_desc[m_tape_motor_mode]); + break; + case 0x023: + // "Tape Drive Control: Record" + // 0=Read, 1=Write + tape_drive.writing = (data & 1); + break; + case 0x024: + // "Tape Drive Control: Mute 1" + // 0=Enable Channel B Audio, 1=Mute + tape_drive.audio_b_mute = (data & 1); + break; + case 0x025: + // "Tape Drive Control: Mute 2" + // 0=Enable Channel A Audio, 1=Mute + tape_drive.audio_a_mute = (data & 1); + break; + case 0x026: + // "Tape Drive Control: Mode" + // If read mode: + // 0=Read Channel B Data, 1 = Read Channel A Data + // If write mode: + // 0=Write Channel B data, 1 = Record Channel B Audio + tape_drive.channel_select = (data & 1); + case 0x027: + break; + // "Tape Drive Control: Erase" + tape_drive.erase = (data & 1); + break; + case 0x040: + // Data to Tape + tape_drive.write_data = (data & 1); + break; + case 0x041: + // "Tape Interrupt Enable" + //if (data & 1) + //logerror("TAPE: Tape Interrupts Enabled\n"); + //else + //logerror("TAPE: Tape Interrupts Disabled\n"); + m_tape_interrupts_enabled = (data & 1); + break; + case 0x042: + // "NOT External Interrupt Enable" + //if (data & 1) + //logerror("TAPE: Cart Bus Interrupts Disabled\n"); + //else + //logerror("TAPE: Cart Bus Interrupts Enabled\n"); + break; + case 0x043: + // "NOT Blank Screen" + if (data & 0x01) + m_intvkbd_text_blanked = 0; + else + m_intvkbd_text_blanked = 1; + break; + case 0x044: + m_intvkbd_keyboard_col &= 0x0e; + m_intvkbd_keyboard_col |= (data&0x01); + break; + case 0x045: + m_intvkbd_keyboard_col &= 0x0d; + m_intvkbd_keyboard_col |= ((data&0x01)<<1); + break; + case 0x046: + m_intvkbd_keyboard_col &= 0x0b; + m_intvkbd_keyboard_col |= ((data&0x01)<<2); + break; + case 0x047: + m_intvkbd_keyboard_col &= 0x07; + m_intvkbd_keyboard_col |= ((data&0x01)<<3); + break; + case 0x80: + // "Clear Tape Interrupt" + //logerror("TAPE: Write to 0x40%02x, clear tape int pending\n",offset); + m_tape_int_pending = 0; + break; + case 0xa0: + // "Clear Clock Interrupt" + //logerror("TAPE: Write to 0x40%02x, clear SR1 int pending\n",offset); + m_sr1_int_pending = 0; + break; + default: + //logerror("%04X: Unknown write %02x to 0x40%02x\n",space.device().safe_pc(),data,offset); + break; + } +} + +#if 0 +static int max_bits = 0; +static unsigned char *tape_data; + +void get_tape_bit(int position, int channel, int *data_present, int *data) +{ + int byte = (position >> 2)*2 + channel; + int data_present_mask = 1 << ((3-(position % 4))*2 + 1); + int data_mask = 1 << ((3-(position % 4))*2); + + //printf("%d\t0x%02x 0x%02x\n",byte,data_present_mask,data_mask); + + if (tape_data[byte] & data_present_mask) + *data_present = 1; + else + *data_present = 0; + + if (tape_data[byte] & data_mask) + *data = 1; + else + *data = 0; +} + +void set_tape_bit(int position, int data) +{ + int byte = (position >> 2)*2 + 1; + int data_present_mask = 1 << ((3-(position % 4))*2 + 1); + int data_mask = 1 << ((3-(position % 4))*2); + + tape_data[byte] |= data_present_mask; + if (data) + tape_data[byte] |= data_mask; + else + tape_data[byte] &= (~data_mask); +} +#endif + +#if defined(LATER) +int intvkbd_tape_init(int id) +{ + FILE *tapefile; + int filesize; + + if (!(tapefile = image_fopen (IO_CASSETTE, id, OSD_FILETYPE_IMAGE, OSD_FOPEN_READ))) + { + return INIT_FAIL; + } + + filesize = osd_fsize(tapefile); + tape_data = (unsigned char *)malloc(filesize); + osd_fread(tapefile, tape_data, filesize); + + osd_fclose(tapefile); + + max_bits = 2*filesize; + + tape_drive.tape_missing = 0; + tape_drive.leader_detect = 0; + tape_drive.ready = 1; + + tape_drive.bit_counter = 0; + return INIT_PASS; +} + +void intvkbd_tape_exit(int id) +{ + FILE *tapefile; + int filesize; + + if (tape_data) + { + if (!(tapefile = image_fopen (IO_CASSETTE, id, OSD_FILETYPE_IMAGE, OSD_FOPEN_RW))) { - case 0x020: - m_tape_motor_mode &= 3; - if (data & 1) - m_tape_motor_mode |= 4; - logerror("TAPE: Motor Mode: %s\n",tape_motor_mode_desc[m_tape_motor_mode]); - break; - case 0x021: - m_tape_motor_mode &= 5; - if (data & 1) - m_tape_motor_mode |= 2; - logerror("TAPE: Motor Mode: %s\n",tape_motor_mode_desc[m_tape_motor_mode]); - break; - case 0x022: - m_tape_motor_mode &= 6; - if (data & 1) - m_tape_motor_mode |= 1; - logerror("TAPE: Motor Mode: %s\n",tape_motor_mode_desc[m_tape_motor_mode]); - break; - case 0x023: - case 0x024: - case 0x025: - case 0x026: - case 0x027: - m_tape_unknown_write[offset - 0x23] = (data & 1); - break; - case 0x040: - m_tape_unknown_write[5] = (data & 1); - break; - case 0x041: - if (data & 1) - logerror("TAPE: Tape Interrupts Enabled\n"); - else - logerror("TAPE: Tape Interrupts Disabled\n"); - m_tape_interrupts_enabled = (data & 1); - break; - case 0x042: - if (data & 1) - logerror("TAPE: Cart Bus Interrupts Disabled\n"); - else - logerror("TAPE: Cart Bus Interrupts Enabled\n"); - break; - case 0x043: - if (data & 0x01) - m_intvkbd_text_blanked = 0; - else - m_intvkbd_text_blanked = 1; - break; - case 0x044: - m_intvkbd_keyboard_col &= 0x0e; - m_intvkbd_keyboard_col |= (data&0x01); - break; - case 0x045: - m_intvkbd_keyboard_col &= 0x0d; - m_intvkbd_keyboard_col |= ((data&0x01)<<1); - break; - case 0x046: - m_intvkbd_keyboard_col &= 0x0b; - m_intvkbd_keyboard_col |= ((data&0x01)<<2); - break; - case 0x047: - m_intvkbd_keyboard_col &= 0x07; - m_intvkbd_keyboard_col |= ((data&0x01)<<3); - break; - case 0x80: - logerror("TAPE: Write to 0x40%02x, clear tape int pending\n",offset); - m_tape_int_pending = 0; - break; - case 0xa0: - logerror("TAPE: Write to 0x40%02x, clear SR1 int pending\n",offset); - m_sr1_int_pending = 0; - break; - case 0xc0: - case 0xc1: - case 0xc2: - case 0xc3: - case 0xc4: - case 0xc5: - case 0xc6: - case 0xc7: - case 0xc8: - case 0xc9: - case 0xca: - case 0xcb: - case 0xcc: - case 0xcd: - case 0xce: - case 0xcf: - /* TMS9927 regs */ - intvkbd_tms9927_w(space, offset-0xc0, data); - break; - default: - logerror("%04X: Unknown write %02x to 0x40%02x\n",space.device().safe_pc(),data,offset); - break; + filesize = osd_fsize(tapefile); + osd_fwrite(tapefile, tape_data, filesize); + osd_fclose(tapefile); + + free(tape_data); + tape_data = 0; + + max_bits = 0; + tape_drive.tape_missing = 1; + tape_drive.bit_counter = 0; + } + } +} + +void update_tape_drive(void) +{ + /* temp */ + + if (tape_drive.writing) + { + if (tape_drive.channel_select == 0) /* data */ + { + set_tape_bit(tape_drive.bit_counter,tape_drive.write_data); + } + else + { + /* recording audio - TBD */ } } else { - mask = m_intvkbd_dualport_ram[offset] & 0x00ff; - m_intvkbd_dualport_ram[offset] = mask | ((data<<8)&0x0300); + int channel; + int data_present; + int data; + + channel = tape_drive.channel_select ^ 1; + + get_tape_bit(tape_drive.bit_counter,channel,&data_present,&data); + + tape_drive.no_data = data_present ^ 1; + tape_drive.read_data = data; + + /* temporary */ + tape_drive.playing = data_present ^ 1; + } + + if (tape_drive.motor_state == 5) /* Playing */ + { + tape_drive.bit_counter++; + if (tape_drive.bit_counter >= max_bits) + tape_drive.bit_counter = max_bits-1; + } + + if (tape_drive.motor_state == 6) /* Rewinding */ + { + tape_drive.bit_counter-=4; + //tape_drive.bit_counter--; + if (tape_drive.bit_counter < 0) + tape_drive.bit_counter = 0; + } + if (tape_drive.motor_state == 7) /* FastFwd */ + { + tape_drive.bit_counter+=2; + //tape_drive.bit_counter++; + if (tape_drive.bit_counter >= max_bits) + tape_drive.bit_counter = max_bits-1; + } + + if ((tape_drive.bit_counter == 0) || (tape_drive.bit_counter == max_bits-1)) + tape_drive.leader_detect = 1; + else + tape_drive.leader_detect = 0; +} +#endif + +//////////// + +READ8_MEMBER( intv_state::intvkbd_periph_r ) +{ + uint8_t value = 0; + switch(offset) { + case 0x06: + if (m_printer_not_busy_enable) + if (m_printer_not_busy) + value |= 0x80; + if (m_printer_no_paper) + value |= 0x10; + //logerror("PeriphRead: 0x%04x->0x%02x\n",offset,value); + + // After one query of busy, + // next time the state is not_busy + if (!m_printer_not_busy) + m_printer_not_busy = true; + + return value; + break; + case 0x07: + + default: + //logerror("PeriphRead: 0x%04x->0x%02x\n",offset,0xff); + return 0xff; + break; } } +WRITE8_MEMBER( intv_state::intvkbd_periph_w ) +{ + switch(offset) { + case 0x06: + //logerror("PeriphWrite: 0x%04x->0x%02x\n",offset,data); + if (data & 0x20) + m_printer_not_busy_enable = true; + else + m_printer_not_busy_enable = false; + break; + case 0x07: + //logerror("Printing: 0x%02x, %c\n",data,data); + // For testing, print to stdout + fputc(data, stdout); + fflush(stdout); + m_printer_not_busy = false; + break; + default: + //logerror("PeriphWrite: 0x%04x->0x%02x\n",offset,data); + break; + } +} READ16_MEMBER( intv_state::intv_stic_r ) { @@ -322,6 +558,13 @@ void intv_state::machine_reset() /* Set initial PC */ m_maincpu->set_state_int(CP1610_R7, 0x1000); + + if (m_is_keybd) + { + m_printer_not_busy = true; // printer state + m_printer_no_paper = false; // printer state + m_printer_not_busy_enable = false; // printer interface state + } } void intv_state::machine_start() @@ -346,12 +589,7 @@ void intv_state::machine_start() save_item(NAME(m_intvkbd_keyboard_col)); save_item(NAME(m_tape_int_pending)); save_item(NAME(m_tape_interrupts_enabled)); - save_item(NAME(m_tape_unknown_write)); save_item(NAME(m_tape_motor_mode)); - save_item(NAME(m_tms9927_num_rows)); - save_item(NAME(m_tms9927_cursor_col)); - save_item(NAME(m_tms9927_cursor_row)); - save_item(NAME(m_tms9927_last_row)); } if (m_cart && m_cart->exists()) @@ -436,3 +674,39 @@ INTERRUPT_GEN_MEMBER(intv_state::intv_interrupt) m_stic->screenrefresh(); } + +#if defined(LATER) + +INTERRUPT_GEN( intvkbd_interrupt2 ) +{ + static int tape_interrupt_divider = 0; + + tape_interrupt_divider++; + tape_interrupt_divider = tape_interrupt_divider % 50; + + if (tape_interrupt_divider == 0) + { +#if 0 + update_tape_drive(); + + /* do sr1 interrupt plus possible tape interrupt */ + if (tape_interrupts_enabled) + tape_int_pending = 1; +#endif + sr1_int_pending = 1; + cpu_set_irq_line(1, 0, PULSE_LINE); + } + else + { + update_tape_drive(); + + /* do only possible tape interrupt */ + if (tape_interrupts_enabled) + { + tape_int_pending = 1; + cpu_set_irq_line(1, 0, PULSE_LINE); + } + } + +} +#endif diff --git a/src/mame/video/intv.cpp b/src/mame/video/intv.cpp index 29e769b85da..49d2360844e 100644 --- a/src/mame/video/intv.cpp +++ b/src/mame/video/intv.cpp @@ -1,108 +1,59 @@ // license:BSD-3-Clause // copyright-holders:Nathan Woods,Frank Palazzolo #include "emu.h" +#include "video/tms9927.h" #include "includes/intv.h" void intv_state::video_start() { - m_tms9927_num_rows = 25; } - -/* very rudimentary support for the tms9927 character generator IC */ - - -READ8_MEMBER( intv_state::intvkbd_tms9927_r ) -{ - uint8_t rv; - switch (offset) - { - case 8: - rv = m_tms9927_cursor_row; - break; - case 9: - /* note: this is 1-based */ - rv = m_tms9927_cursor_col; - break; - case 11: - m_tms9927_last_row = (m_tms9927_last_row + 1) % m_tms9927_num_rows; - rv = m_tms9927_last_row; - break; - default: - rv = 0; - } - return rv; -} - -WRITE8_MEMBER( intv_state::intvkbd_tms9927_w ) -{ - switch (offset) - { - case 3: - m_tms9927_num_rows = (data & 0x3f) + 1; - break; - case 6: - m_tms9927_last_row = data; - break; - case 11: - m_tms9927_last_row = (m_tms9927_last_row + 1) % m_tms9927_num_rows; - break; - case 12: - /* note: this is 1-based */ - m_tms9927_cursor_col = data; - break; - case 13: - m_tms9927_cursor_row = data; - break; - } -} - - uint32_t intv_state::screen_update_intv(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { m_stic->screen_update(screen, bitmap, cliprect); return 0; } - uint32_t intv_state::screen_update_intvkbd(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { - uint8_t *videoram = m_videoram; - int x,y,offs; - int current_row; -// char c; - /* Draw the underlying INTV screen first */ m_stic->screen_update(screen, bitmap, cliprect); /* if the intvkbd text is not blanked, overlay it */ if (!m_intvkbd_text_blanked) { - current_row = (m_tms9927_last_row + 1) % m_tms9927_num_rows; - for(y=0;y<24;y++) + uint8_t *videoram = m_videoram; + int xoffset = STIC_OVERSCAN_LEFT_WIDTH*STIC_X_SCALE*INTVKBD_X_SCALE; + int yoffset = STIC_OVERSCAN_TOP_HEIGHT*STIC_Y_SCALE*INTVKBD_Y_SCALE; + + rectangle cursor_rect; + m_crtc->cursor_bounds(cursor_rect); + int cursor_col = cursor_rect.min_x / 8; + int cursor_row = cursor_rect.min_y / 8; + + int current_row = m_crtc->upscroll_offset() % 24; + + for(int y=0;y<24;y++) { - for(x=0;x<40;x++) + for(int x=0;x<40;x++) { - offs = current_row*64+x; - - m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, - videoram[offs], - 7, /* white */ - 0,0, - x<<3,y<<3, 0); - } - if (current_row == m_tms9927_cursor_row) - { - /* draw the cursor as a solid white block */ - /* (should use a filled rect here!) */ - + if ((cursor_row == current_row) && (cursor_col == x+1)) { + /* draw the cursor as a solid white block */ m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, 191, /* a block */ 7, /* white */ 0,0, - (m_tms9927_cursor_col-1)<<3,y<<3, 0); + xoffset+(x<<3), yoffset+(y<<3), 0); + } else { + int offs = current_row*64+x; + m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, + videoram[offs], + 7, /* white */ + 0,0, + xoffset+(x<<3), yoffset+(y<<3), 0); + } } - current_row = (current_row + 1) % m_tms9927_num_rows; + current_row = (current_row + 1) % 24; } } diff --git a/src/mame/video/stic.cpp b/src/mame/video/stic.cpp index 20106936c97..705c895d9ae 100644 --- a/src/mame/video/stic.cpp +++ b/src/mame/video/stic.cpp @@ -924,7 +924,7 @@ WRITE16_MEMBER( stic_device::write ) case STIC_CSR + STIC_CSR1: case STIC_CSR + STIC_CSR2: case STIC_CSR + STIC_CSR3: - logerror("Setting color_stack[%x] = %x (%x)\n", offset & (STIC_CSRS - 1),data & STIC_CSR_BG, space.device().safe_pc()); + //logerror("Setting color_stack[%x] = %x (%x)\n", offset & (STIC_CSRS - 1),data & STIC_CSR_BG, space.device().safe_pc()); break; // Border Color case STIC_BCR: