intvkbd - mostly internal driver improvements (#2045)

WIP - commit. Not much visible progress yet, except that the screen alignment is now correct. But internally things are getting better. Rebased on top of mame0182

Changed intvkbd to use generic TMS9927 support
Modded TMS9927 to allow for driver-specific overscan areas
Aligned STIC and TMS9927 graphics properly
Added prelim support for testing intvkbd printer
Add proper documented memory addresses for tape drive
Bring in commented tape drive code from old MESS source (wip)
This commit is contained in:
Frank Palazzolo 2017-02-07 22:26:41 -05:00 committed by ajrhacker
parent 5990685b53
commit 8ef98237ab
7 changed files with 553 additions and 304 deletions

View File

@ -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));
}

View File

@ -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<tms9927_device &>(device).m_hpixels_per_column = pixels; }
static void set_region_tag(device_t &device, const char *tag) { downcast<tms9927_device &>(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<tms9927_device &>(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<uint8_t> 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;

View File

@ -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 */

View File

@ -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<cpu_device> m_maincpu;
required_device<ay8914_device> m_sound;
required_device<stic_device> m_stic;
optional_device<tms9927_device> m_crtc;
optional_device<intv_cart_slot_device> m_cart;
optional_shared_ptr<uint16_t> m_intvkbd_dualport_ram;
optional_shared_ptr<uint8_t> 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);

View File

@ -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

View File

@ -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;
}
}

View File

@ -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: