diff --git a/src/mame/machine/decocass.c b/src/mame/machine/decocass.c index 9ba90842500..5d764c0d42e 100644 --- a/src/mame/machine/decocass.c +++ b/src/mame/machine/decocass.c @@ -932,7 +932,7 @@ READ8_MEMBER(decocass_state::decocass_e5xx_r) /* E5x2-E5x3 and mirrors */ if (2 == (offset & E5XX_MASK)) { - UINT8 bot_eot = (tape_get_status_bits(m_cassette) >> 5) & 1; + UINT8 bot_eot = (m_cassette->get_status_bits() >> 5) & 1; data = (BIT(m_i8041_p1, 7) << 0) | /* D0 = P17 - REQ/ */ @@ -942,7 +942,7 @@ READ8_MEMBER(decocass_state::decocass_e5xx_r) ((bot_eot) << 4) | /* D4 = BOT/EOT (direct from drive) */ (1 << 5) | /* D5 floating input */ (1 << 6) | /* D6 floating input */ - (!tape_is_present(m_cassette) << 7); /* D7 = cassette present */ + (!m_cassette->is_present() << 7); /* D7 = cassette present */ LOG(4,("%10s 6502-PC: %04x decocass_e5xx_r(%02x): $%02x <- STATUS (%s%s%s%s%s%s%s%s)\n", space.machine().time().as_string(6), @@ -1468,7 +1468,7 @@ WRITE8_MEMBER(decocass_state::i8041_p1_w) newspeed = (data & 0x04) ? -1 : -7; else if ((data & 0x30) == 0x10) newspeed = (data & 0x04) ? 1 : 7; - tape_change_speed(m_cassette, newspeed); + m_cassette->change_speed(newspeed); } m_i8041_p1 = data; @@ -1522,7 +1522,7 @@ READ8_MEMBER(decocass_state::i8041_p2_r) { UINT8 data; - data = (m_i8041_p2 & ~0xe0) | tape_get_status_bits(m_cassette); + data = (m_i8041_p2 & ~0xe0) | m_cassette->get_status_bits(); if (data != m_i8041_p2_read_latch) { diff --git a/src/mame/machine/decocass_tape.c b/src/mame/machine/decocass_tape.c index 766a91a6964..32833437c1e 100644 --- a/src/mame/machine/decocass_tape.c +++ b/src/mame/machine/decocass_tape.c @@ -8,7 +8,6 @@ #include "cpu/m6502/m6502.h" #include "cpu/mcs48/mcs48.h" #include "machine/decocass_tape.h" -#include "devlegcy.h" #define LOG_CASSETTE_STATE 0 @@ -16,57 +15,6 @@ CASSETTE DEVICE INTERFACE ***************************************************************************/ -/* regions within the virtual tape */ -enum tape_region -{ - REGION_LEADER, /* in clear leader section */ - REGION_LEADER_GAP, /* in gap between leader and BOT */ - REGION_BOT, /* in BOT hole */ - REGION_BOT_GAP, /* in gap between BOT hole and data */ - REGION_DATA_BLOCK_0, /* in data block 0 */ - REGION_DATA_BLOCK_255 = REGION_DATA_BLOCK_0 + 255, - REGION_EOT_GAP, /* in gap between data and EOT hole */ - REGION_EOT, /* in EOT hole */ - REGION_TRAILER_GAP, /* in gap between trailer and EOT */ - REGION_TRAILER /* in clear trailer section */ -}; - - -/* bytes within a data block on a virtual tape */ -enum tape_byte -{ - BYTE_PRE_GAP_0, /* 34 bytes of gap, clock held to 0, no data */ - BYTE_PRE_GAP_33 = BYTE_PRE_GAP_0 + 33, - BYTE_LEADIN, /* 1 leadin byte, clocked value 0x00 */ - BYTE_HEADER, /* 1 header byte, clocked value 0xAA */ - BYTE_DATA_0, /* 256 bytes of data, clocked */ - BYTE_DATA_255 = BYTE_DATA_0 + 255, - BYTE_CRC16_MSB, /* 2 bytes of CRC, clocked MSB first, then LSB */ - BYTE_CRC16_LSB, - BYTE_TRAILER, /* 1 trailer byte, clocked value 0xAA */ - BYTE_LEADOUT, /* 1 leadout byte, clocked value 0x00 */ - BYTE_LONGCLOCK, /* 1 longclock byte, clock held to 1, no data */ - BYTE_POSTGAP_0, /* 34 bytes of gap, no clock, no data */ - BYTE_POSTGAP_33 = BYTE_POSTGAP_0 + 33, - BYTE_BLOCK_TOTAL /* total number of bytes in block */ -}; - - -/* state of the tape */ -struct tape_state -{ - running_machine * machine; /* pointer back to the machine */ - emu_timer * timer; /* timer for running the tape */ - INT8 speed; /* speed: <-1=fast rewind, -1=reverse, 0=stopped, 1=normal, >1=fast forward */ - tape_region region; /* current region */ - tape_byte bytenum; /* byte number within a datablock */ - UINT8 bitnum; /* bit number within a byte */ - UINT32 clockpos; /* the current clock position of the tape */ - UINT32 numclocks; /* total number of clocks on the entire tape */ - UINT16 crc16[256]; /* CRC16 for each block */ -}; - - /* number of tape clock pulses per second */ #define TAPE_CLOCKRATE 4800 #define TAPE_CLOCKS_PER_BIT 2 @@ -104,20 +52,88 @@ struct tape_state #define REGION_BOT_GAP_LEN_CLOCKS TAPE_MSEC_TO_CLOCKS(300) /* 300ms */ #define REGION_BOT_GAP_END_CLOCK (REGION_BOT_GAP_START_CLOCK+REGION_BOT_GAP_LEN_CLOCKS) +static UINT16 tape_crc16_byte(UINT16 crc, UINT8 data); -/*------------------------------------------------- - get_safe_token - makes sure that the passed - in device is, in fact, an IDE controller --------------------------------------------------*/ +const device_type DECOCASS_TAPE = &device_creator; -INLINE tape_state *get_safe_token(device_t *device) +decocass_tape_device::decocass_tape_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, DECOCASS_TAPE, "DECO Cassette Tape", tag, owner, clock, "decocass_tape", __FILE__), + m_tape_timer(NULL), + m_speed(0), + m_bitnum(0), + m_clockpos(0), + m_numclocks(0) { - assert(device != NULL); - assert(device->type() == DECOCASS_TAPE); - - return (tape_state *)downcast(device)->token(); + for (int i = 0; i < 256; i++) + m_crc16[i] = 0; } +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void decocass_tape_device::device_config_complete() +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void decocass_tape_device::device_start() +{ + int curblock, offs, numblocks; + + /* fetch the data pointer */ + m_tape_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(decocass_tape_device::tape_clock_callback), this)); + if (region() == NULL) + return; + UINT8 *regionbase = *region(); + + /* scan for the first non-empty block in the image */ + for (offs = region()->bytes() - 1; offs >= 0; offs--) + if (regionbase[offs] != 0) + break; + numblocks = ((offs | 0xff) + 1) / 256; + assert(numblocks < ARRAY_LENGTH(m_crc16)); + + /* compute the total length */ + m_numclocks = REGION_BOT_GAP_END_CLOCK + numblocks * BYTE_BLOCK_TOTAL * 16 + REGION_BOT_GAP_END_CLOCK; + + /* compute CRCs for each block */ + for (curblock = 0; curblock < numblocks; curblock++) + { + UINT16 crc = 0; + int testval; + + /* first CRC the 256 bytes of data */ + for (offs = 256 * curblock; offs < 256 * curblock + 256; offs++) + crc = tape_crc16_byte(crc, regionbase[offs]); + + /* then find a pair of bytes that will bring the CRC to 0 (any better way than brute force?) */ + for (testval = 0; testval < 0x10000; testval++) + if (tape_crc16_byte(tape_crc16_byte(crc, testval >> 8), testval) == 0) + break; + m_crc16[curblock] = testval; + } + + /* register states */ + save_item(NAME(m_speed)); + save_item(NAME(m_bitnum)); + save_item(NAME(m_clockpos)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void decocass_tape_device::device_reset() +{ + /* turn the tape off */ + change_speed(0); +} /*------------------------------------------------- tape_crc16_byte - accumulate 8 bits worth of @@ -139,33 +155,32 @@ static UINT16 tape_crc16_byte(UINT16 crc, UINT8 data) return crc; } - /*------------------------------------------------- tape_describe_state - create a string that describes the state of the tape -------------------------------------------------*/ -static const char *tape_describe_state(tape_state *tape) +const char *decocass_tape_device::describe_state() { static char buffer[40]; char temprname[40]; const char *rname = temprname; - if (tape->region == REGION_LEADER) + if (m_region == REGION_LEADER) rname = "LEAD"; - else if (tape->region == REGION_LEADER_GAP) + else if (m_region == REGION_LEADER_GAP) rname = "LGAP"; - else if (tape->region == REGION_BOT) + else if (m_region == REGION_BOT) rname = "BOT "; - else if (tape->region == REGION_BOT_GAP) + else if (m_region == REGION_BOT_GAP) rname = "BGAP"; - else if (tape->region == REGION_TRAILER) + else if (m_region == REGION_TRAILER) rname = "TRLR"; - else if (tape->region == REGION_TRAILER_GAP) + else if (m_region == REGION_TRAILER_GAP) rname = "TGAP"; - else if (tape->region == REGION_EOT) + else if (m_region == REGION_EOT) rname = "EOT "; - else if (tape->region == REGION_EOT_GAP) + else if (m_region == REGION_EOT_GAP) rname = "EGAP"; else { @@ -173,39 +188,39 @@ static const char *tape_describe_state(tape_state *tape) const char *bname = tempbname; int clk; - if (tape->bytenum <= BYTE_PRE_GAP_33) - sprintf(tempbname, "PR%02d", tape->bytenum - BYTE_PRE_GAP_0); - else if (tape->bytenum == BYTE_LEADIN) + if (m_bytenum <= BYTE_PRE_GAP_33) + sprintf(tempbname, "PR%02d", m_bytenum - BYTE_PRE_GAP_0); + else if (m_bytenum == BYTE_LEADIN) bname = "LDIN"; - else if (tape->bytenum == BYTE_HEADER) + else if (m_bytenum == BYTE_HEADER) bname = "HEAD"; - else if (tape->bytenum <= BYTE_DATA_255) - sprintf(tempbname, "BY%02X", tape->bytenum - BYTE_DATA_0); - else if (tape->bytenum == BYTE_CRC16_MSB) + else if (m_bytenum <= BYTE_DATA_255) + sprintf(tempbname, "BY%02X", m_bytenum - BYTE_DATA_0); + else if (m_bytenum == BYTE_CRC16_MSB) bname = "CRCM"; - else if (tape->bytenum == BYTE_CRC16_LSB) + else if (m_bytenum == BYTE_CRC16_LSB) bname = "CRCL"; - else if (tape->bytenum == BYTE_TRAILER) + else if (m_bytenum == BYTE_TRAILER) bname = "TRLR"; - else if (tape->bytenum == BYTE_LEADOUT) + else if (m_bytenum == BYTE_LEADOUT) bname = "LOUT"; - else if (tape->bytenum == BYTE_LONGCLOCK) + else if (m_bytenum == BYTE_LONGCLOCK) bname = "LONG"; else - sprintf(tempbname, "PO%02d", tape->bytenum - BYTE_POSTGAP_0); + sprintf(tempbname, "PO%02d", m_bytenum - BYTE_POSTGAP_0); /* in the main data area, the clock alternates at the clock rate */ - if (tape->bytenum >= BYTE_LEADIN && tape->bytenum <= BYTE_LEADOUT) - clk = ((UINT32)(tape->clockpos - REGION_BOT_GAP_END_CLOCK) & 1) ? 0 : 1; - else if (tape->bytenum == BYTE_LONGCLOCK) + if (m_bytenum >= BYTE_LEADIN && m_bytenum <= BYTE_LEADOUT) + clk = ((UINT32)(m_clockpos - REGION_BOT_GAP_END_CLOCK) & 1) ? 0 : 1; + else if (m_bytenum == BYTE_LONGCLOCK) clk = 1; else clk = 0; - sprintf(temprname, "BL%02X.%4s.%d.%d", tape->region - REGION_DATA_BLOCK_0, bname, tape->bitnum, clk); + sprintf(temprname, "BL%02X.%4s.%d.%d", m_region - REGION_DATA_BLOCK_0, bname, m_bitnum, clk); } - sprintf(buffer, "{%9d=%s}", tape->clockpos, rname); + sprintf(buffer, "{%9d=%s}", m_clockpos, rname); return buffer; } @@ -215,57 +230,54 @@ static const char *tape_describe_state(tape_state *tape) to increment/decrement the tape location -------------------------------------------------*/ -static TIMER_CALLBACK( tape_clock_callback ) +TIMER_CALLBACK_MEMBER( decocass_tape_device::tape_clock_callback ) { - device_t *device = (device_t *)ptr; - tape_state *tape = get_safe_token(device); - /* advance by one clock in the desired direction */ - if (tape->speed < 0 && tape->clockpos > 0) - tape->clockpos--; - else if (tape->speed > 0 && tape->clockpos < tape->numclocks) - tape->clockpos++; + if (m_speed < 0 && m_clockpos > 0) + m_clockpos--; + else if (m_speed > 0 && m_clockpos < m_numclocks) + m_clockpos++; /* look for states before the start of data */ - if (tape->clockpos < REGION_LEADER_END_CLOCK) - tape->region = REGION_LEADER; - else if (tape->clockpos < REGION_LEADER_GAP_END_CLOCK) - tape->region = REGION_LEADER_GAP; - else if (tape->clockpos < REGION_BOT_END_CLOCK) - tape->region = REGION_BOT; - else if (tape->clockpos < REGION_BOT_GAP_END_CLOCK) - tape->region = REGION_BOT_GAP; + if (m_clockpos < REGION_LEADER_END_CLOCK) + m_region = REGION_LEADER; + else if (m_clockpos < REGION_LEADER_GAP_END_CLOCK) + m_region = REGION_LEADER_GAP; + else if (m_clockpos < REGION_BOT_END_CLOCK) + m_region = REGION_BOT; + else if (m_clockpos < REGION_BOT_GAP_END_CLOCK) + m_region = REGION_BOT_GAP; /* look for states after the end of data */ - else if (tape->clockpos >= tape->numclocks - REGION_LEADER_END_CLOCK) - tape->region = REGION_TRAILER; - else if (tape->clockpos >= tape->numclocks - REGION_LEADER_GAP_END_CLOCK) - tape->region = REGION_TRAILER_GAP; - else if (tape->clockpos >= tape->numclocks - REGION_BOT_END_CLOCK) - tape->region = REGION_EOT; - else if (tape->clockpos >= tape->numclocks - REGION_BOT_GAP_END_CLOCK) - tape->region = REGION_EOT_GAP; + else if (m_clockpos >= m_numclocks - REGION_LEADER_END_CLOCK) + m_region = REGION_TRAILER; + else if (m_clockpos >= m_numclocks - REGION_LEADER_GAP_END_CLOCK) + m_region = REGION_TRAILER_GAP; + else if (m_clockpos >= m_numclocks - REGION_BOT_END_CLOCK) + m_region = REGION_EOT; + else if (m_clockpos >= m_numclocks - REGION_BOT_GAP_END_CLOCK) + m_region = REGION_EOT_GAP; /* everything else is data */ else { - UINT32 dataclock = tape->clockpos - REGION_BOT_GAP_END_CLOCK; + UINT32 dataclock = m_clockpos - REGION_BOT_GAP_END_CLOCK; /* compute the block number */ - tape->region = (tape_region)(REGION_DATA_BLOCK_0 + dataclock / (TAPE_CLOCKS_PER_BYTE * BYTE_BLOCK_TOTAL)); - dataclock -= (tape->region - REGION_DATA_BLOCK_0) * TAPE_CLOCKS_PER_BYTE * BYTE_BLOCK_TOTAL; + m_region = (tape_region)(REGION_DATA_BLOCK_0 + dataclock / (TAPE_CLOCKS_PER_BYTE * BYTE_BLOCK_TOTAL)); + dataclock -= (m_region - REGION_DATA_BLOCK_0) * TAPE_CLOCKS_PER_BYTE * BYTE_BLOCK_TOTAL; /* compute the byte within the block */ - tape->bytenum = (tape_byte)(dataclock / TAPE_CLOCKS_PER_BYTE); - dataclock -= tape->bytenum * TAPE_CLOCKS_PER_BYTE; + m_bytenum = (tape_byte)(dataclock / TAPE_CLOCKS_PER_BYTE); + dataclock -= m_bytenum * TAPE_CLOCKS_PER_BYTE; /* compute the bit within the byte */ - tape->bitnum = dataclock / TAPE_CLOCKS_PER_BIT; + m_bitnum = dataclock / TAPE_CLOCKS_PER_BIT; } /* log */ if (LOG_CASSETTE_STATE) - tape_describe_state(tape); + describe_state(); } @@ -274,28 +286,27 @@ static TIMER_CALLBACK( tape_clock_callback ) bits from the tape -------------------------------------------------*/ -UINT8 tape_get_status_bits(device_t *device) +UINT8 decocass_tape_device::get_status_bits() { - tape_state *tape = get_safe_token(device); UINT8 tape_bits = 0; /* bit 0x20 is the BOT/EOT signal, which is also set in the leader/trailer area */ - if (tape->region == REGION_LEADER || tape->region == REGION_BOT || tape->region == REGION_EOT || tape->region == REGION_TRAILER) + if (m_region == REGION_LEADER || m_region == REGION_BOT || m_region == REGION_EOT || m_region == REGION_TRAILER) tape_bits |= 0x20; /* bit 0x40 is the clock, which is only valid in some areas of the data block */ /* bit 0x80 is the data, which is only valid in some areas of the data block */ - if (tape->region >= REGION_DATA_BLOCK_0 && tape->region <= REGION_DATA_BLOCK_255) + if (m_region >= REGION_DATA_BLOCK_0 && m_region <= REGION_DATA_BLOCK_255) { - int blocknum = tape->region - REGION_DATA_BLOCK_0; + int blocknum = m_region - REGION_DATA_BLOCK_0; UINT8 byteval = 0x00; /* in the main data area, the clock alternates at the clock rate */ - if (tape->bytenum >= BYTE_LEADIN && tape->bytenum <= BYTE_LEADOUT) - tape_bits |= ((UINT32)(tape->clockpos - REGION_BOT_GAP_END_CLOCK) & 1) ? 0x00 : 0x40; + if (m_bytenum >= BYTE_LEADIN && m_bytenum <= BYTE_LEADOUT) + tape_bits |= ((UINT32)(m_clockpos - REGION_BOT_GAP_END_CLOCK) & 1) ? 0x00 : 0x40; /* in the longclock area, the clock holds high */ - else if (tape->bytenum == BYTE_LONGCLOCK) + else if (m_bytenum == BYTE_LONGCLOCK) tape_bits |= 0x40; /* everywhere else, the clock holds to 0 */ @@ -303,23 +314,23 @@ UINT8 tape_get_status_bits(device_t *device) ; /* lead-in and lead-out bytes are 0xAA */ - if (tape->bytenum == BYTE_HEADER || tape->bytenum == BYTE_TRAILER) + if (m_bytenum == BYTE_HEADER || m_bytenum == BYTE_TRAILER) byteval = 0xaa; /* data block bytes are data */ - else if (tape->bytenum >= BYTE_DATA_0 && tape->bytenum <= BYTE_DATA_255) - byteval = static_cast(*device->region())[blocknum * 256 + (tape->bytenum - BYTE_DATA_0)]; + else if (m_bytenum >= BYTE_DATA_0 && m_bytenum <= BYTE_DATA_255) + byteval = static_cast(*region())[blocknum * 256 + (m_bytenum - BYTE_DATA_0)]; /* CRC MSB */ - else if (tape->bytenum == BYTE_CRC16_MSB) - byteval = tape->crc16[blocknum] >> 8; + else if (m_bytenum == BYTE_CRC16_MSB) + byteval = m_crc16[blocknum] >> 8; /* CRC LSB */ - else if (tape->bytenum == BYTE_CRC16_LSB) - byteval = tape->crc16[blocknum]; + else if (m_bytenum == BYTE_CRC16_LSB) + byteval = m_crc16[blocknum]; /* select the appropriate bit from the byte and move to the upper bit */ - if ((byteval >> tape->bitnum) & 1) + if ((byteval >> m_bitnum) & 1) tape_bits |= 0x80; } return tape_bits; @@ -331,9 +342,9 @@ UINT8 tape_get_status_bits(device_t *device) present -------------------------------------------------*/ -UINT8 tape_is_present(device_t *device) +UINT8 decocass_tape_device::is_present() { - return device->region() != NULL; + return region() != NULL; } @@ -342,14 +353,13 @@ UINT8 tape_is_present(device_t *device) playback -------------------------------------------------*/ -void tape_change_speed(device_t *device, INT8 newspeed) +void decocass_tape_device::change_speed(INT8 newspeed) { - tape_state *tape = get_safe_token(device); attotime newperiod; INT8 absnewspeed; /* do nothing if speed has not changed */ - if (tape->speed == newspeed) + if (m_speed == newspeed) return; /* compute how fast to run the tape timer */ @@ -360,107 +370,6 @@ void tape_change_speed(device_t *device, INT8 newspeed) newperiod = attotime::from_hz(TAPE_CLOCKRATE * absnewspeed); /* set the new speed */ - tape->timer->adjust(newperiod, 0, newperiod); - tape->speed = newspeed; -} - - -/*------------------------------------------------- - device start callback --------------------------------------------------*/ - -static DEVICE_START( decocass_tape ) -{ - tape_state *tape = get_safe_token(device); - int curblock, offs, numblocks; - - /* validate some basic stuff */ - assert(device != NULL); - assert(device->static_config() == NULL); - - /* fetch the data pointer */ - tape->timer = device->machine().scheduler().timer_alloc(FUNC(tape_clock_callback), (void *)device); - if (device->region() == NULL) - return; - UINT8 *regionbase = *device->region(); - - /* scan for the first non-empty block in the image */ - for (offs = device->region()->bytes() - 1; offs >= 0; offs--) - if (regionbase[offs] != 0) - break; - numblocks = ((offs | 0xff) + 1) / 256; - assert(numblocks < ARRAY_LENGTH(tape->crc16)); - - /* compute the total length */ - tape->numclocks = REGION_BOT_GAP_END_CLOCK + numblocks * BYTE_BLOCK_TOTAL * 16 + REGION_BOT_GAP_END_CLOCK; - - /* compute CRCs for each block */ - for (curblock = 0; curblock < numblocks; curblock++) - { - UINT16 crc = 0; - int testval; - - /* first CRC the 256 bytes of data */ - for (offs = 256 * curblock; offs < 256 * curblock + 256; offs++) - crc = tape_crc16_byte(crc, regionbase[offs]); - - /* then find a pair of bytes that will bring the CRC to 0 (any better way than brute force?) */ - for (testval = 0; testval < 0x10000; testval++) - if (tape_crc16_byte(tape_crc16_byte(crc, testval >> 8), testval) == 0) - break; - tape->crc16[curblock] = testval; - } - - /* register states */ - device->save_item(NAME(tape->speed)); - device->save_item(NAME(tape->bitnum)); - device->save_item(NAME(tape->clockpos)); -} - - -/*------------------------------------------------- - device reset callback --------------------------------------------------*/ - -static DEVICE_RESET( decocass_tape ) -{ - /* turn the tape off */ - tape_change_speed(device, 0); -} - - -const device_type DECOCASS_TAPE = &device_creator; - -decocass_tape_device::decocass_tape_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, DECOCASS_TAPE, "DECO Cassette Tape", tag, owner, clock, "decocass_tape", __FILE__) -{ - m_token = global_alloc_clear(tape_state); -} - -//------------------------------------------------- -// device_config_complete - perform any -// operations now that the configuration is -// complete -//------------------------------------------------- - -void decocass_tape_device::device_config_complete() -{ -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void decocass_tape_device::device_start() -{ - DEVICE_START_NAME( decocass_tape )(this); -} - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void decocass_tape_device::device_reset() -{ - DEVICE_RESET_NAME( decocass_tape )(this); + m_tape_timer->adjust(newperiod, 0, newperiod); + m_speed = newspeed; } diff --git a/src/mame/machine/decocass_tape.h b/src/mame/machine/decocass_tape.h index b42a2e083a4..fe61707eb7f 100644 --- a/src/mame/machine/decocass_tape.h +++ b/src/mame/machine/decocass_tape.h @@ -5,27 +5,70 @@ class decocass_tape_device : public device_t { public: decocass_tape_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - ~decocass_tape_device() { global_free(m_token); } + ~decocass_tape_device() {} - // access to legacy token - void *token() const { assert(m_token != NULL); return m_token; } + UINT8 get_status_bits(); + UINT8 is_present(); + void change_speed(INT8 newspeed); + protected: // device-level overrides virtual void device_config_complete(); virtual void device_start(); virtual void device_reset(); + private: + /* regions within the virtual tape */ + enum tape_region + { + REGION_LEADER, /* in clear leader section */ + REGION_LEADER_GAP, /* in gap between leader and BOT */ + REGION_BOT, /* in BOT hole */ + REGION_BOT_GAP, /* in gap between BOT hole and data */ + REGION_DATA_BLOCK_0, /* in data block 0 */ + REGION_DATA_BLOCK_255 = REGION_DATA_BLOCK_0 + 255, + REGION_EOT_GAP, /* in gap between data and EOT hole */ + REGION_EOT, /* in EOT hole */ + REGION_TRAILER_GAP, /* in gap between trailer and EOT */ + REGION_TRAILER /* in clear trailer section */ + }; + + + /* bytes within a data block on a virtual tape */ + enum tape_byte + { + BYTE_PRE_GAP_0, /* 34 bytes of gap, clock held to 0, no data */ + BYTE_PRE_GAP_33 = BYTE_PRE_GAP_0 + 33, + BYTE_LEADIN, /* 1 leadin byte, clocked value 0x00 */ + BYTE_HEADER, /* 1 header byte, clocked value 0xAA */ + BYTE_DATA_0, /* 256 bytes of data, clocked */ + BYTE_DATA_255 = BYTE_DATA_0 + 255, + BYTE_CRC16_MSB, /* 2 bytes of CRC, clocked MSB first, then LSB */ + BYTE_CRC16_LSB, + BYTE_TRAILER, /* 1 trailer byte, clocked value 0xAA */ + BYTE_LEADOUT, /* 1 leadout byte, clocked value 0x00 */ + BYTE_LONGCLOCK, /* 1 longclock byte, clock held to 1, no data */ + BYTE_POSTGAP_0, /* 34 bytes of gap, no clock, no data */ + BYTE_POSTGAP_33 = BYTE_POSTGAP_0 + 33, + BYTE_BLOCK_TOTAL /* total number of bytes in block */ + }; + // internal state - void *m_token; + emu_timer * m_tape_timer; /* timer for running the tape */ + INT8 m_speed; /* speed: <-1=fast rewind, -1=reverse, 0=stopped, 1=normal, >1=fast forward */ + tape_region m_region; /* current region */ + tape_byte m_bytenum; /* byte number within a datablock */ + UINT8 m_bitnum; /* bit number within a byte */ + UINT32 m_clockpos; /* the current clock position of the tape */ + UINT32 m_numclocks; /* total number of clocks on the entire tape */ + UINT16 m_crc16[256]; /* CRC16 for each block */ + + const char *describe_state(); + TIMER_CALLBACK_MEMBER( tape_clock_callback ); }; extern const device_type DECOCASS_TAPE; -UINT8 tape_get_status_bits(device_t *device); -UINT8 tape_is_present(device_t *device); -void tape_change_speed(device_t *device, INT8 newspeed); - - #define MCFG_DECOCASS_TAPE_ADD(_tag) \ MCFG_DEVICE_ADD(_tag, DECOCASS_TAPE, 0)