summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/hp_taco.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/hp_taco.cpp')
-rw-r--r--src/devices/machine/hp_taco.cpp1982
1 files changed, 991 insertions, 991 deletions
diff --git a/src/devices/machine/hp_taco.cpp b/src/devices/machine/hp_taco.cpp
index 76203d31ee3..eb94faf3b05 100644
--- a/src/devices/machine/hp_taco.cpp
+++ b/src/devices/machine/hp_taco.cpp
@@ -148,8 +148,8 @@
// Timers
enum {
- TAPE_TMR_ID,
- HOLE_TMR_ID
+ TAPE_TMR_ID,
+ HOLE_TMR_ID
};
// Constants
@@ -178,52 +178,52 @@ enum {
// Parts of command register
#define CMD_CODE(reg) \
- (((reg) >> 10) & 0x1f)
+ (((reg) >> 10) & 0x1f)
#define DIR_FWD(reg) \
- (BIT(reg , 15))
+ (BIT(reg , 15))
#define SPEED_FAST(reg) \
- (BIT(reg , 7))
+ (BIT(reg , 7))
#define CMD_OPT(reg) \
- (BIT(reg , 6))
+ (BIT(reg , 6))
#define UNKNOWN_B9(reg) \
- (BIT(reg , 9))
+ (BIT(reg , 9))
#define DIR_FWD_MASK BIT_MASK(15) // Direction = forward
#define SPEED_FAST_MASK BIT_MASK(7) // Speed = fast
// Commands
enum {
- CMD_INDTA_INGAP, // 00: scan for data first then for gap
- CMD_UNK_01, // 01: unknown
- CMD_FINAL_GAP, // 02: write final gap
- CMD_INIT_WRITE, // 03: write words for tape formatting
- CMD_STOP, // 04: stop
- CMD_UNK_05, // 05: unknown
- CMD_SET_TRACK, // 06: set A/B track
- CMD_UNK_07, // 07: unknown
- CMD_UNK_08, // 08: unknown
- CMD_UNK_09, // 09: unknown
- CMD_MOVE, // 0a: move tape
- CMD_UNK_0b, // 0b: unknown
- CMD_INGAP_MOVE, // 0c: scan for gap then move a bit further (used to gain some margin when inverting tape movement)
- CMD_UNK_0d, // 0d: unknown
- CMD_CLEAR, // 0e: clear errors/unlatch status bits
- CMD_UNK_0f, // 0f: unknown
- CMD_NOT_INDTA, // 10: scan for end of data
- CMD_UNK_11, // 11: unknown
- CMD_UNK_12, // 12: unknown
- CMD_UNK_13, // 13: unknown
- CMD_UNK_14, // 14: unknown
- CMD_UNK_15, // 15: unknown
- CMD_WRITE_IRG, // 16: write inter-record gap
- CMD_UNK_17, // 17: unknown
- CMD_SCAN_RECORDS, // 18: scan records (count IRGs)
- CMD_RECORD_WRITE, // 19: write record words
- CMD_MOVE_INDTA, // 1a: move then scan for data
- CMD_UNK_1b, // 1b: unknown (for now it seems harmless to handle it as NOP)
- CMD_DELTA_MOVE_HOLE, // 1c: move tape a given distance, intr at end or first hole found (whichever comes first)
- CMD_START_READ, // 1d: start record reading
- CMD_DELTA_MOVE_IRG, // 1e: move tape a given distance, detect gaps in parallel
- CMD_END_READ // 1f: stop reading
+ CMD_INDTA_INGAP, // 00: scan for data first then for gap
+ CMD_UNK_01, // 01: unknown
+ CMD_FINAL_GAP, // 02: write final gap
+ CMD_INIT_WRITE, // 03: write words for tape formatting
+ CMD_STOP, // 04: stop
+ CMD_UNK_05, // 05: unknown
+ CMD_SET_TRACK, // 06: set A/B track
+ CMD_UNK_07, // 07: unknown
+ CMD_UNK_08, // 08: unknown
+ CMD_UNK_09, // 09: unknown
+ CMD_MOVE, // 0a: move tape
+ CMD_UNK_0b, // 0b: unknown
+ CMD_INGAP_MOVE, // 0c: scan for gap then move a bit further (used to gain some margin when inverting tape movement)
+ CMD_UNK_0d, // 0d: unknown
+ CMD_CLEAR, // 0e: clear errors/unlatch status bits
+ CMD_UNK_0f, // 0f: unknown
+ CMD_NOT_INDTA, // 10: scan for end of data
+ CMD_UNK_11, // 11: unknown
+ CMD_UNK_12, // 12: unknown
+ CMD_UNK_13, // 13: unknown
+ CMD_UNK_14, // 14: unknown
+ CMD_UNK_15, // 15: unknown
+ CMD_WRITE_IRG, // 16: write inter-record gap
+ CMD_UNK_17, // 17: unknown
+ CMD_SCAN_RECORDS, // 18: scan records (count IRGs)
+ CMD_RECORD_WRITE, // 19: write record words
+ CMD_MOVE_INDTA, // 1a: move then scan for data
+ CMD_UNK_1b, // 1b: unknown (for now it seems harmless to handle it as NOP)
+ CMD_DELTA_MOVE_HOLE, // 1c: move tape a given distance, intr at end or first hole found (whichever comes first)
+ CMD_START_READ, // 1d: start record reading
+ CMD_DELTA_MOVE_IRG, // 1e: move tape a given distance, detect gaps in parallel
+ CMD_END_READ // 1f: stop reading
};
// Bits of status register
@@ -250,17 +250,17 @@ enum {
// O O O O
//
static const hp_taco_device::tape_pos_t tape_holes[] = {
- (hp_taco_device::tape_pos_t)(23.891 * ONE_INCH_POS), // 24 - 0.218 / 2
- (hp_taco_device::tape_pos_t)(24.109 * ONE_INCH_POS), // 24 + 0.218 / 2
- (hp_taco_device::tape_pos_t)(35.891 * ONE_INCH_POS), // 36 - 0.218 / 2
- (hp_taco_device::tape_pos_t)(36.109 * ONE_INCH_POS), // 36 + 0.218 / 2
- (hp_taco_device::tape_pos_t)(47.891 * ONE_INCH_POS), // 48 - 0.218 / 2
- (hp_taco_device::tape_pos_t)(48.109 * ONE_INCH_POS), // 48 + 0.218 / 2
- 72 * ONE_INCH_POS, // 72
- 1752 * ONE_INCH_POS, // 1752
- 1776 * ONE_INCH_POS, // 1776
- 1788 * ONE_INCH_POS, // 1788
- 1800 * ONE_INCH_POS // 1800
+ (hp_taco_device::tape_pos_t)(23.891 * ONE_INCH_POS), // 24 - 0.218 / 2
+ (hp_taco_device::tape_pos_t)(24.109 * ONE_INCH_POS), // 24 + 0.218 / 2
+ (hp_taco_device::tape_pos_t)(35.891 * ONE_INCH_POS), // 36 - 0.218 / 2
+ (hp_taco_device::tape_pos_t)(36.109 * ONE_INCH_POS), // 36 + 0.218 / 2
+ (hp_taco_device::tape_pos_t)(47.891 * ONE_INCH_POS), // 48 - 0.218 / 2
+ (hp_taco_device::tape_pos_t)(48.109 * ONE_INCH_POS), // 48 + 0.218 / 2
+ 72 * ONE_INCH_POS, // 72
+ 1752 * ONE_INCH_POS, // 1752
+ 1776 * ONE_INCH_POS, // 1776
+ 1788 * ONE_INCH_POS, // 1788
+ 1800 * ONE_INCH_POS // 1800
};
// Device type definition
@@ -268,144 +268,144 @@ const device_type HP_TACO = &device_creator<hp_taco_device>;
// Constructors
hp_taco_device::hp_taco_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname)
- : device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__),
- device_image_interface(mconfig , *this),
- m_irq_handler(*this),
- m_flg_handler(*this),
- m_sts_handler(*this),
- m_tape_pos(TAPE_INIT_POS),
- m_image_dirty(false)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__),
+ device_image_interface(mconfig , *this),
+ m_irq_handler(*this),
+ m_flg_handler(*this),
+ m_sts_handler(*this),
+ m_tape_pos(TAPE_INIT_POS),
+ m_image_dirty(false)
{
- clear_state();
+ clear_state();
}
hp_taco_device::hp_taco_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : device_t(mconfig, HP_TACO, "HP TACO", tag, owner, clock, "TACO", __FILE__),
- device_image_interface(mconfig , *this),
- m_irq_handler(*this),
- m_flg_handler(*this),
- m_sts_handler(*this),
- m_tape_pos(TAPE_INIT_POS),
- m_image_dirty(false)
+ : device_t(mconfig, HP_TACO, "HP TACO", tag, owner, clock, "TACO", __FILE__),
+ device_image_interface(mconfig , *this),
+ m_irq_handler(*this),
+ m_flg_handler(*this),
+ m_sts_handler(*this),
+ m_tape_pos(TAPE_INIT_POS),
+ m_image_dirty(false)
{
- clear_state();
+ clear_state();
}
WRITE16_MEMBER(hp_taco_device::reg_w)
{
- LOG_0(("wr R%u = %04x\n", 4 + offset , data));
-
- // Any I/O activity clears IRQ
- irq_w(false);
-
- switch (offset) {
- case 0:
- // Data register
- m_data_reg = data;
- m_data_reg_full = true;
- break;
-
- case 1:
- // Command register
- start_cmd_exec(data & CMD_REG_MASK);
- break;
-
- case 2:
- // Tachometer register
- m_tach_reg = data;
- break;
-
- case 3:
- // Timing register
- m_timing_reg = data;
- break;
- }
+ LOG_0(("wr R%u = %04x\n", 4 + offset , data));
+
+ // Any I/O activity clears IRQ
+ irq_w(false);
+
+ switch (offset) {
+ case 0:
+ // Data register
+ m_data_reg = data;
+ m_data_reg_full = true;
+ break;
+
+ case 1:
+ // Command register
+ start_cmd_exec(data & CMD_REG_MASK);
+ break;
+
+ case 2:
+ // Tachometer register
+ m_tach_reg = data;
+ break;
+
+ case 3:
+ // Timing register
+ m_timing_reg = data;
+ break;
+ }
}
READ16_MEMBER(hp_taco_device::reg_r)
{
- UINT16 res = 0;
+ UINT16 res = 0;
- // Any I/O activity clears IRQ
- irq_w(false);
+ // Any I/O activity clears IRQ
+ irq_w(false);
- switch (offset) {
- case 0:
- // Data register
- res = m_data_reg;
- break;
+ switch (offset) {
+ case 0:
+ // Data register
+ res = m_data_reg;
+ break;
- case 1:
- // Command & status register
- res = (m_cmd_reg & CMD_REG_MASK) | (m_status_reg & STATUS_REG_MASK);
- break;
+ case 1:
+ // Command & status register
+ res = (m_cmd_reg & CMD_REG_MASK) | (m_status_reg & STATUS_REG_MASK);
+ break;
- case 2:
- // Tachometer register
- res = m_tach_reg;
- break;
+ case 2:
+ // Tachometer register
+ res = m_tach_reg;
+ break;
- case 3:
- // Checksum register: it clears when read
- res = m_checksum_reg;
- m_checksum_reg = 0;
- break;
- }
+ case 3:
+ // Checksum register: it clears when read
+ res = m_checksum_reg;
+ m_checksum_reg = 0;
+ break;
+ }
- LOG_0(("rd R%u = %04x\n", 4 + offset , res));
+ LOG_0(("rd R%u = %04x\n", 4 + offset , res));
- return res;
+ return res;
}
READ_LINE_MEMBER(hp_taco_device::flg_r)
{
- return m_flg;
+ return m_flg;
}
READ_LINE_MEMBER(hp_taco_device::sts_r)
{
- return m_sts;
+ return m_sts;
}
// device_config_complete
void hp_taco_device::device_config_complete()
{
- LOG(("device_config_complete"));
+ LOG(("device_config_complete"));
update_names();
}
// device_start
void hp_taco_device::device_start()
{
- LOG(("device_start"));
- m_irq_handler.resolve_safe();
- m_flg_handler.resolve_safe();
- m_sts_handler.resolve_safe();
-
- save_item(NAME(m_data_reg));
- save_item(NAME(m_data_reg_full));
- save_item(NAME(m_cmd_reg));
- save_item(NAME(m_cmd_state));
- save_item(NAME(m_status_reg));
- save_item(NAME(m_tach_reg));
- save_item(NAME(m_checksum_reg));
- save_item(NAME(m_timing_reg));
- save_item(NAME(m_irq));
- save_item(NAME(m_flg));
- save_item(NAME(m_sts));
- save_item(NAME(m_tape_pos));
- save_item(NAME(m_start_time));
- save_item(NAME(m_tape_fwd));
- save_item(NAME(m_tape_fast));
- save_item(NAME(m_image_dirty));
- save_item(NAME(m_tape_wr));
- save_item(NAME(m_rw_pos));
- save_item(NAME(m_next_word));
- save_item(NAME(m_rd_it_valid));
- save_item(NAME(m_gap_detect_start));
-
- m_tape_timer = timer_alloc(TAPE_TMR_ID);
- m_hole_timer = timer_alloc(HOLE_TMR_ID);
+ LOG(("device_start"));
+ m_irq_handler.resolve_safe();
+ m_flg_handler.resolve_safe();
+ m_sts_handler.resolve_safe();
+
+ save_item(NAME(m_data_reg));
+ save_item(NAME(m_data_reg_full));
+ save_item(NAME(m_cmd_reg));
+ save_item(NAME(m_cmd_state));
+ save_item(NAME(m_status_reg));
+ save_item(NAME(m_tach_reg));
+ save_item(NAME(m_checksum_reg));
+ save_item(NAME(m_timing_reg));
+ save_item(NAME(m_irq));
+ save_item(NAME(m_flg));
+ save_item(NAME(m_sts));
+ save_item(NAME(m_tape_pos));
+ save_item(NAME(m_start_time));
+ save_item(NAME(m_tape_fwd));
+ save_item(NAME(m_tape_fast));
+ save_item(NAME(m_image_dirty));
+ save_item(NAME(m_tape_wr));
+ save_item(NAME(m_rw_pos));
+ save_item(NAME(m_next_word));
+ save_item(NAME(m_rd_it_valid));
+ save_item(NAME(m_gap_detect_start));
+
+ m_tape_timer = timer_alloc(TAPE_TMR_ID);
+ m_hole_timer = timer_alloc(HOLE_TMR_ID);
}
// device_stop
@@ -416,593 +416,593 @@ void hp_taco_device::device_stop()
// device_reset
void hp_taco_device::device_reset()
{
- LOG(("device_reset"));
- clear_state();
+ LOG(("device_reset"));
+ clear_state();
- m_irq = false;
- m_flg = true;
+ m_irq = false;
+ m_flg = true;
- m_irq_handler(false);
- m_flg_handler(true);
- set_error(false);
+ m_irq_handler(false);
+ m_flg_handler(true);
+ set_error(false);
}
void hp_taco_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
- if (CMD_CODE(m_cmd_reg) != CMD_STOP) {
- update_tape_pos();
- }
-
- switch (id) {
- case TAPE_TMR_ID:
- LOG_0(("Tape tmr @%g\n" , machine().time().as_double()));
-
- tape_pos_t length;
-
- switch (CMD_CODE(m_cmd_reg)) {
- case CMD_INDTA_INGAP:
- if (m_cmd_state == 0) {
- m_cmd_state = 1;
- tape_pos_t target = m_tape_pos;
- if (next_n_gap(target, 1, MIN_IRG_LENGTH)) {
- m_tape_timer->adjust(time_to_target(target));
- }
- return;
- }
- break;
-
- case CMD_RECORD_WRITE:
- if (m_cmd_state == 0) {
- if (m_rd_it->second == PREAMBLE_WORD) {
- LOG_0(("Got preamble\n"));
- m_cmd_state = 1;
- // m_rw_pos already at correct position
- m_tape_timer->adjust(fetch_next_wr_word());
- break;
- } else {
- adv_res_t res = adv_it(m_rd_it);
- if (res != ADV_NO_MORE_DATA) {
- m_tape_timer->adjust(time_to_rd_next_word(m_rw_pos));
- }
- // No IRQ
- return;
- }
- }
- // Intentional fall-through
- case CMD_INIT_WRITE:
- write_word(m_rw_pos , m_next_word , length);
- pos_offset(m_rw_pos , length);
- // Just to be sure..
- m_tape_pos = m_rw_pos;
- m_tape_timer->adjust(fetch_next_wr_word());
- break;
-
- case CMD_STOP:
- move_tape_pos(m_tape_fast ? FAST_BRAKE_DIST : SLOW_BRAKE_DIST);
- stop_tape();
- break;
-
- case CMD_INGAP_MOVE:
- if (m_cmd_state == 0) {
- m_cmd_state = 1;
- m_tape_timer->adjust(time_to_tach_pulses());
- return;
- }
- break;
-
- case CMD_FINAL_GAP:
- case CMD_WRITE_IRG:
- write_gap(m_rw_pos , m_tape_pos);
- m_hole_timer->reset();
- break;
-
- case CMD_SCAN_RECORDS:
- if (m_cmd_state == 0) {
- m_cmd_state = 1;
- tape_pos_t target = m_tape_pos;
- if (next_n_gap(target, 0x10000U - m_tach_reg, MIN_IRG_LENGTH)) {
- LOG_0(("%u gaps @%d\n" , 0x10000U - m_tach_reg, target));
- m_tape_timer->adjust(time_to_target(target));
- }
- return;
- } else {
- m_hole_timer->reset();
- }
- break;
-
- case CMD_MOVE_INDTA:
- if (m_cmd_state == 0) {
- if (next_data(m_rd_it , m_tape_pos , true)) {
- m_cmd_state = 1;
- m_tape_timer->adjust(time_to_target(farthest_end(m_rd_it)));
- }
- // No IRQ
- return;
- }
- // m_cmd_state == 1 -> IRQ & cmd end
- break;
-
- case CMD_DELTA_MOVE_HOLE:
- case CMD_DELTA_MOVE_IRG:
- // Interrupt at end of movement
- m_hole_timer->reset();
- break;
-
- case CMD_START_READ:
- {
- bool set_intr = true;
- // Just to be sure..
- m_tape_pos = m_rw_pos;
- if (m_cmd_state == 0) {
- set_intr = false;
- if (m_rd_it->second == PREAMBLE_WORD) {
- m_cmd_state = 1;
- }
- LOG_0(("Got preamble\n"));
- } else {
- m_data_reg = m_rd_it->second;
- m_checksum_reg += m_data_reg;
- LOG_0(("RD %04x\n" , m_data_reg));
- }
- adv_res_t res = adv_it(m_rd_it);
- LOG_0(("adv_it %d\n" , res));
- if (res == ADV_NO_MORE_DATA) {
- m_rd_it_valid = false;
- } else {
- if (res == ADV_DISCONT_DATA) {
- // Hit a gap, restart preamble search
- m_cmd_state = 0;
- }
- m_tape_timer->adjust(time_to_rd_next_word(m_rw_pos));
- }
- if (!set_intr) {
- return;
- }
- }
- break;
-
- case CMD_END_READ:
- {
- m_tape_pos = m_rw_pos;
- // Note: checksum is not updated
- m_data_reg = m_rd_it->second;
- LOG_0(("Final RD %04x\n" , m_data_reg));
- adv_res_t res = adv_it(m_rd_it);
- if (res == ADV_NO_MORE_DATA) {
- m_rd_it_valid = false;
- }
- m_hole_timer->reset();
- }
- break;
-
- default:
- // Other commands: just raise irq
- break;
- }
- irq_w(true);
- break;
-
- case HOLE_TMR_ID:
- LOG_0(("Hole tmr @%g\n" , machine().time().as_double()));
-
- BIT_SET(m_status_reg , STATUS_HOLE_BIT);
-
- switch (CMD_CODE(m_cmd_reg)) {
- case CMD_FINAL_GAP:
- case CMD_WRITE_IRG:
- write_gap(m_rw_pos , m_tape_pos);
- m_rw_pos = m_tape_pos;
- break;
-
- case CMD_SCAN_RECORDS:
- case CMD_DELTA_MOVE_HOLE:
- // Cmds 18 & 1c are terminated at first hole
- m_tape_timer->reset();
- irq_w(true);
- // No reloading of hole timer
- return;
-
- case CMD_DELTA_MOVE_IRG:
- // TODO: update r6
- m_hole_timer->adjust(time_to_next_hole());
- // No IRQ at holes
- return;
-
- case CMD_START_READ:
- case CMD_END_READ:
- set_error(true);
- break;
-
- default:
- // Other cmds: default processing (update tape pos, set IRQ, schedule timer for next hole)
- break;
- }
-
- irq_w(true);
- m_hole_timer->adjust(time_to_next_hole());
- break;
-
- default:
- break;
- }
+ if (CMD_CODE(m_cmd_reg) != CMD_STOP) {
+ update_tape_pos();
+ }
+
+ switch (id) {
+ case TAPE_TMR_ID:
+ LOG_0(("Tape tmr @%g\n" , machine().time().as_double()));
+
+ tape_pos_t length;
+
+ switch (CMD_CODE(m_cmd_reg)) {
+ case CMD_INDTA_INGAP:
+ if (m_cmd_state == 0) {
+ m_cmd_state = 1;
+ tape_pos_t target = m_tape_pos;
+ if (next_n_gap(target, 1, MIN_IRG_LENGTH)) {
+ m_tape_timer->adjust(time_to_target(target));
+ }
+ return;
+ }
+ break;
+
+ case CMD_RECORD_WRITE:
+ if (m_cmd_state == 0) {
+ if (m_rd_it->second == PREAMBLE_WORD) {
+ LOG_0(("Got preamble\n"));
+ m_cmd_state = 1;
+ // m_rw_pos already at correct position
+ m_tape_timer->adjust(fetch_next_wr_word());
+ break;
+ } else {
+ adv_res_t res = adv_it(m_rd_it);
+ if (res != ADV_NO_MORE_DATA) {
+ m_tape_timer->adjust(time_to_rd_next_word(m_rw_pos));
+ }
+ // No IRQ
+ return;
+ }
+ }
+ // Intentional fall-through
+ case CMD_INIT_WRITE:
+ write_word(m_rw_pos , m_next_word , length);
+ pos_offset(m_rw_pos , length);
+ // Just to be sure..
+ m_tape_pos = m_rw_pos;
+ m_tape_timer->adjust(fetch_next_wr_word());
+ break;
+
+ case CMD_STOP:
+ move_tape_pos(m_tape_fast ? FAST_BRAKE_DIST : SLOW_BRAKE_DIST);
+ stop_tape();
+ break;
+
+ case CMD_INGAP_MOVE:
+ if (m_cmd_state == 0) {
+ m_cmd_state = 1;
+ m_tape_timer->adjust(time_to_tach_pulses());
+ return;
+ }
+ break;
+
+ case CMD_FINAL_GAP:
+ case CMD_WRITE_IRG:
+ write_gap(m_rw_pos , m_tape_pos);
+ m_hole_timer->reset();
+ break;
+
+ case CMD_SCAN_RECORDS:
+ if (m_cmd_state == 0) {
+ m_cmd_state = 1;
+ tape_pos_t target = m_tape_pos;
+ if (next_n_gap(target, 0x10000U - m_tach_reg, MIN_IRG_LENGTH)) {
+ LOG_0(("%u gaps @%d\n" , 0x10000U - m_tach_reg, target));
+ m_tape_timer->adjust(time_to_target(target));
+ }
+ return;
+ } else {
+ m_hole_timer->reset();
+ }
+ break;
+
+ case CMD_MOVE_INDTA:
+ if (m_cmd_state == 0) {
+ if (next_data(m_rd_it , m_tape_pos , true)) {
+ m_cmd_state = 1;
+ m_tape_timer->adjust(time_to_target(farthest_end(m_rd_it)));
+ }
+ // No IRQ
+ return;
+ }
+ // m_cmd_state == 1 -> IRQ & cmd end
+ break;
+
+ case CMD_DELTA_MOVE_HOLE:
+ case CMD_DELTA_MOVE_IRG:
+ // Interrupt at end of movement
+ m_hole_timer->reset();
+ break;
+
+ case CMD_START_READ:
+ {
+ bool set_intr = true;
+ // Just to be sure..
+ m_tape_pos = m_rw_pos;
+ if (m_cmd_state == 0) {
+ set_intr = false;
+ if (m_rd_it->second == PREAMBLE_WORD) {
+ m_cmd_state = 1;
+ }
+ LOG_0(("Got preamble\n"));
+ } else {
+ m_data_reg = m_rd_it->second;
+ m_checksum_reg += m_data_reg;
+ LOG_0(("RD %04x\n" , m_data_reg));
+ }
+ adv_res_t res = adv_it(m_rd_it);
+ LOG_0(("adv_it %d\n" , res));
+ if (res == ADV_NO_MORE_DATA) {
+ m_rd_it_valid = false;
+ } else {
+ if (res == ADV_DISCONT_DATA) {
+ // Hit a gap, restart preamble search
+ m_cmd_state = 0;
+ }
+ m_tape_timer->adjust(time_to_rd_next_word(m_rw_pos));
+ }
+ if (!set_intr) {
+ return;
+ }
+ }
+ break;
+
+ case CMD_END_READ:
+ {
+ m_tape_pos = m_rw_pos;
+ // Note: checksum is not updated
+ m_data_reg = m_rd_it->second;
+ LOG_0(("Final RD %04x\n" , m_data_reg));
+ adv_res_t res = adv_it(m_rd_it);
+ if (res == ADV_NO_MORE_DATA) {
+ m_rd_it_valid = false;
+ }
+ m_hole_timer->reset();
+ }
+ break;
+
+ default:
+ // Other commands: just raise irq
+ break;
+ }
+ irq_w(true);
+ break;
+
+ case HOLE_TMR_ID:
+ LOG_0(("Hole tmr @%g\n" , machine().time().as_double()));
+
+ BIT_SET(m_status_reg , STATUS_HOLE_BIT);
+
+ switch (CMD_CODE(m_cmd_reg)) {
+ case CMD_FINAL_GAP:
+ case CMD_WRITE_IRG:
+ write_gap(m_rw_pos , m_tape_pos);
+ m_rw_pos = m_tape_pos;
+ break;
+
+ case CMD_SCAN_RECORDS:
+ case CMD_DELTA_MOVE_HOLE:
+ // Cmds 18 & 1c are terminated at first hole
+ m_tape_timer->reset();
+ irq_w(true);
+ // No reloading of hole timer
+ return;
+
+ case CMD_DELTA_MOVE_IRG:
+ // TODO: update r6
+ m_hole_timer->adjust(time_to_next_hole());
+ // No IRQ at holes
+ return;
+
+ case CMD_START_READ:
+ case CMD_END_READ:
+ set_error(true);
+ break;
+
+ default:
+ // Other cmds: default processing (update tape pos, set IRQ, schedule timer for next hole)
+ break;
+ }
+
+ irq_w(true);
+ m_hole_timer->adjust(time_to_next_hole());
+ break;
+
+ default:
+ break;
+ }
}
void hp_taco_device::clear_state(void)
{
- m_data_reg = 0;
- m_data_reg_full = false;
- m_cmd_reg = 0;
- m_status_reg = 0;
- m_tach_reg = 0;
- m_checksum_reg = 0;
- m_timing_reg = 0;
- m_cmd_state = 0;
- // m_tape_pos is not reset, tape stays where it is
- m_start_time = attotime::never;
- m_tape_fwd = false;
- m_tape_fast = false;
- // m_image_dirty is not touched
- m_tape_wr = false;
- m_rw_pos = 0;
- m_next_word = 0;
- m_rd_it_valid = false;
- m_gap_detect_start = NULL_TAPE_POS;
-
- set_tape_present(false);
- set_tape_present(is_loaded());
+ m_data_reg = 0;
+ m_data_reg_full = false;
+ m_cmd_reg = 0;
+ m_status_reg = 0;
+ m_tach_reg = 0;
+ m_checksum_reg = 0;
+ m_timing_reg = 0;
+ m_cmd_state = 0;
+ // m_tape_pos is not reset, tape stays where it is
+ m_start_time = attotime::never;
+ m_tape_fwd = false;
+ m_tape_fast = false;
+ // m_image_dirty is not touched
+ m_tape_wr = false;
+ m_rw_pos = 0;
+ m_next_word = 0;
+ m_rd_it_valid = false;
+ m_gap_detect_start = NULL_TAPE_POS;
+
+ set_tape_present(false);
+ set_tape_present(is_loaded());
}
void hp_taco_device::irq_w(bool state)
{
- if (state != m_irq) {
- m_irq = state;
- m_irq_handler(state);
- LOG_0(("IRQ = %d\n" , state));
- }
+ if (state != m_irq) {
+ m_irq = state;
+ m_irq_handler(state);
+ LOG_0(("IRQ = %d\n" , state));
+ }
}
void hp_taco_device::set_error(bool state)
{
- m_sts = !state;
- m_sts_handler(m_sts);
- LOG_0(("error = %d\n" , state));
+ m_sts = !state;
+ m_sts_handler(m_sts);
+ LOG_0(("error = %d\n" , state));
}
unsigned hp_taco_device::speed_to_tick_freq(void) const
{
- return m_tape_fast ? TACH_FREQ_FAST * TAPE_POS_FRACT : TACH_FREQ_SLOW * TAPE_POS_FRACT;
+ return m_tape_fast ? TACH_FREQ_FAST * TAPE_POS_FRACT : TACH_FREQ_SLOW * TAPE_POS_FRACT;
}
bool hp_taco_device::pos_offset(tape_pos_t& pos , tape_pos_t offset) const
{
- if (offset == 0) {
- return true;
- }
-
- if (!m_tape_fwd) {
- offset = -offset;
- }
-
- pos += offset;
-
- // In real life tape would unspool..
- if (pos > TAPE_LENGTH) {
- pos = TAPE_LENGTH;
- return false;
- } else if (pos < 0) {
- pos = 0;
- return false;
- } else {
- return true;
- }
+ if (offset == 0) {
+ return true;
+ }
+
+ if (!m_tape_fwd) {
+ offset = -offset;
+ }
+
+ pos += offset;
+
+ // In real life tape would unspool..
+ if (pos > TAPE_LENGTH) {
+ pos = TAPE_LENGTH;
+ return false;
+ } else if (pos < 0) {
+ pos = 0;
+ return false;
+ } else {
+ return true;
+ }
}
void hp_taco_device::move_tape_pos(tape_pos_t delta_pos)
{
- tape_pos_t tape_start_pos = m_tape_pos;
- if (!pos_offset(m_tape_pos , delta_pos)) {
- LOG(("Tape unspooled!\n"));
- }
- m_start_time = machine().time();
- LOG_0(("Tape pos = %u\n" , m_tape_pos));
- if (any_hole(tape_start_pos , m_tape_pos)) {
- // Crossed one or more holes
- BIT_SET(m_status_reg , STATUS_HOLE_BIT);
- }
+ tape_pos_t tape_start_pos = m_tape_pos;
+ if (!pos_offset(m_tape_pos , delta_pos)) {
+ LOG(("Tape unspooled!\n"));
+ }
+ m_start_time = machine().time();
+ LOG_0(("Tape pos = %u\n" , m_tape_pos));
+ if (any_hole(tape_start_pos , m_tape_pos)) {
+ // Crossed one or more holes
+ BIT_SET(m_status_reg , STATUS_HOLE_BIT);
+ }
}
void hp_taco_device::update_tape_pos(void)
{
- if (m_start_time.is_never()) {
- // Tape not moving
- return;
- }
-
- attotime delta_time(machine().time() - m_start_time);
- LOG_0(("delta_time = %g\n" , delta_time.as_double()));
- // How many tachometer ticks has the tape moved?
- tape_pos_t delta_tach = (tape_pos_t)(delta_time.as_ticks(speed_to_tick_freq()));
- LOG_0(("delta_tach = %u\n" , delta_tach));
-
- move_tape_pos(delta_tach);
-
- // Gap detection
- bool gap_detected = false;
- if (m_gap_detect_start != NULL_TAPE_POS && abs(m_gap_detect_start - m_tape_pos) >= MIN_IRG_LENGTH) {
- tape_pos_t tmp = m_tape_pos;
- pos_offset(tmp , -MIN_IRG_LENGTH);
- gap_detected = just_gap(tmp , m_tape_pos);
- }
- if (gap_detected) {
- BIT_SET(m_status_reg, STATUS_GAP_BIT);
- } else {
- BIT_CLR(m_status_reg, STATUS_GAP_BIT);
- }
+ if (m_start_time.is_never()) {
+ // Tape not moving
+ return;
+ }
+
+ attotime delta_time(machine().time() - m_start_time);
+ LOG_0(("delta_time = %g\n" , delta_time.as_double()));
+ // How many tachometer ticks has the tape moved?
+ tape_pos_t delta_tach = (tape_pos_t)(delta_time.as_ticks(speed_to_tick_freq()));
+ LOG_0(("delta_tach = %u\n" , delta_tach));
+
+ move_tape_pos(delta_tach);
+
+ // Gap detection
+ bool gap_detected = false;
+ if (m_gap_detect_start != NULL_TAPE_POS && abs(m_gap_detect_start - m_tape_pos) >= MIN_IRG_LENGTH) {
+ tape_pos_t tmp = m_tape_pos;
+ pos_offset(tmp , -MIN_IRG_LENGTH);
+ gap_detected = just_gap(tmp , m_tape_pos);
+ }
+ if (gap_detected) {
+ BIT_SET(m_status_reg, STATUS_GAP_BIT);
+ } else {
+ BIT_CLR(m_status_reg, STATUS_GAP_BIT);
+ }
}
void hp_taco_device::ensure_a_lt_b(tape_pos_t& a , tape_pos_t& b)
{
- if (a > b) {
- // Ensure A always comes before B
- tape_pos_t tmp;
- tmp = a;
- a = b;
- b = tmp;
- }
+ if (a > b) {
+ // Ensure A always comes before B
+ tape_pos_t tmp;
+ tmp = a;
+ a = b;
+ b = tmp;
+ }
}
// Is there any hole in a given section of tape?
bool hp_taco_device::any_hole(tape_pos_t tape_pos_a , tape_pos_t tape_pos_b)
{
- ensure_a_lt_b(tape_pos_a , tape_pos_b);
+ ensure_a_lt_b(tape_pos_a , tape_pos_b);
- for (tape_pos_t hole : tape_holes) {
- if (tape_pos_a < hole && tape_pos_b >= hole) {
- return true;
- }
- }
+ for (tape_pos_t hole : tape_holes) {
+ if (tape_pos_a < hole && tape_pos_b >= hole) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
// Position of next hole tape will reach in a given direction
hp_taco_device::tape_pos_t hp_taco_device::next_hole(void) const
{
- if (m_tape_fwd) {
- for (tape_pos_t hole : tape_holes) {
- if (hole > m_tape_pos) {
- LOG_0(("next hole fwd @%u = %u\n" , m_tape_pos , hole));
- return hole;
- }
- }
- // No more holes: will hit end of tape
- return TAPE_LENGTH;
- } else {
- for (int i = (sizeof(tape_holes) / sizeof(tape_holes[ 0 ])) - 1; i >= 0; i--) {
- if (tape_holes[ i ] < m_tape_pos) {
- LOG_0(("next hole rev @%u = %u\n" , m_tape_pos , tape_holes[ i ]));
- return tape_holes[ i ];
- }
- }
- // No more holes: will hit start of tape
- return 0;
- }
+ if (m_tape_fwd) {
+ for (tape_pos_t hole : tape_holes) {
+ if (hole > m_tape_pos) {
+ LOG_0(("next hole fwd @%u = %u\n" , m_tape_pos , hole));
+ return hole;
+ }
+ }
+ // No more holes: will hit end of tape
+ return TAPE_LENGTH;
+ } else {
+ for (int i = (sizeof(tape_holes) / sizeof(tape_holes[ 0 ])) - 1; i >= 0; i--) {
+ if (tape_holes[ i ] < m_tape_pos) {
+ LOG_0(("next hole rev @%u = %u\n" , m_tape_pos , tape_holes[ i ]));
+ return tape_holes[ i ];
+ }
+ }
+ // No more holes: will hit start of tape
+ return 0;
+ }
}
attotime hp_taco_device::time_to_distance(tape_pos_t distance) const
{
- // +1 for rounding
- return attotime::from_ticks(distance + 1 , speed_to_tick_freq());
+ // +1 for rounding
+ return attotime::from_ticks(distance + 1 , speed_to_tick_freq());
}
attotime hp_taco_device::time_to_target(tape_pos_t target) const
{
- return time_to_distance(abs(target - m_tape_pos));
+ return time_to_distance(abs(target - m_tape_pos));
}
bool hp_taco_device::start_tape_cmd(UINT16 cmd_reg , UINT16 must_be_1 , UINT16 must_be_0)
{
- m_cmd_reg = cmd_reg;
-
- UINT16 to_be_tested = (m_cmd_reg & CMD_REG_MASK) | (m_status_reg & STATUS_REG_MASK);
- // Bits in STATUS_ERR_MASK must always be 0
- must_be_0 |= STATUS_ERR_MASK;
-
- // It's not an error if the error state is already set (sts false)
- if (((to_be_tested & (must_be_1 | must_be_0)) ^ must_be_1) != 0) {
- set_error(true);
- return false;
- } else {
- bool prev_tape_wr = m_tape_wr;
- bool prev_tape_fwd = m_tape_fwd;
- bool prev_tape_fast = m_tape_fast;
- bool not_moving = m_start_time.is_never();
-
- m_start_time = machine().time();
- m_tape_wr = (must_be_0 & STATUS_WPR_MASK) != 0;
- m_tape_fwd = DIR_FWD(m_cmd_reg);
- m_tape_fast = SPEED_FAST(m_cmd_reg);
- // TODO: remove?
- BIT_CLR(m_status_reg, STATUS_HOLE_BIT);
-
- if (m_tape_wr) {
- // Write command: disable gap detector
- m_gap_detect_start = NULL_TAPE_POS;
- BIT_CLR(m_status_reg, STATUS_GAP_BIT);
- m_image_dirty = true;
- } else if (not_moving || prev_tape_wr != m_tape_wr || prev_tape_fwd != m_tape_fwd || prev_tape_fast != m_tape_fast) {
- // Tape started right now, switched from writing to reading, direction changed or speed changed: (re)start gap detector
- m_gap_detect_start = m_tape_pos;
- BIT_CLR(m_status_reg, STATUS_GAP_BIT);
- }
- return true;
- }
+ m_cmd_reg = cmd_reg;
+
+ UINT16 to_be_tested = (m_cmd_reg & CMD_REG_MASK) | (m_status_reg & STATUS_REG_MASK);
+ // Bits in STATUS_ERR_MASK must always be 0
+ must_be_0 |= STATUS_ERR_MASK;
+
+ // It's not an error if the error state is already set (sts false)
+ if (((to_be_tested & (must_be_1 | must_be_0)) ^ must_be_1) != 0) {
+ set_error(true);
+ return false;
+ } else {
+ bool prev_tape_wr = m_tape_wr;
+ bool prev_tape_fwd = m_tape_fwd;
+ bool prev_tape_fast = m_tape_fast;
+ bool not_moving = m_start_time.is_never();
+
+ m_start_time = machine().time();
+ m_tape_wr = (must_be_0 & STATUS_WPR_MASK) != 0;
+ m_tape_fwd = DIR_FWD(m_cmd_reg);
+ m_tape_fast = SPEED_FAST(m_cmd_reg);
+ // TODO: remove?
+ BIT_CLR(m_status_reg, STATUS_HOLE_BIT);
+
+ if (m_tape_wr) {
+ // Write command: disable gap detector
+ m_gap_detect_start = NULL_TAPE_POS;
+ BIT_CLR(m_status_reg, STATUS_GAP_BIT);
+ m_image_dirty = true;
+ } else if (not_moving || prev_tape_wr != m_tape_wr || prev_tape_fwd != m_tape_fwd || prev_tape_fast != m_tape_fast) {
+ // Tape started right now, switched from writing to reading, direction changed or speed changed: (re)start gap detector
+ m_gap_detect_start = m_tape_pos;
+ BIT_CLR(m_status_reg, STATUS_GAP_BIT);
+ }
+ return true;
+ }
}
void hp_taco_device::stop_tape(void)
{
- m_start_time = attotime::never;
- m_gap_detect_start = NULL_TAPE_POS;
+ m_start_time = attotime::never;
+ m_gap_detect_start = NULL_TAPE_POS;
}
hp_taco_device::tape_track_t& hp_taco_device::current_track(void)
{
- return m_tracks[ BIT(m_status_reg , STATUS_TRACKB_BIT) ];
+ return m_tracks[ BIT(m_status_reg , STATUS_TRACKB_BIT) ];
}
// Return physical length of a 16-bit word on tape
hp_taco_device::tape_pos_t hp_taco_device::word_length(tape_word_t w)
{
- unsigned zeros , ones;
+ unsigned zeros , ones;
- // pop count of w
- ones = (w & 0x5555) + ((w >> 1) & 0x5555);
- ones = (ones & 0x3333) + ((ones >> 2) & 0x3333);
- ones = (ones & 0x0f0f) + ((ones >> 4) & 0x0f0f);
- ones = (ones & 0x00ff) + ((ones >> 8) & 0x00ff);
+ // pop count of w
+ ones = (w & 0x5555) + ((w >> 1) & 0x5555);
+ ones = (ones & 0x3333) + ((ones >> 2) & 0x3333);
+ ones = (ones & 0x0f0f) + ((ones >> 4) & 0x0f0f);
+ ones = (ones & 0x00ff) + ((ones >> 8) & 0x00ff);
- zeros = 16 - ones;
+ zeros = 16 - ones;
- return zeros * ZERO_BIT_LEN + (ones + 1) * ONE_BIT_LEN;
+ return zeros * ZERO_BIT_LEN + (ones + 1) * ONE_BIT_LEN;
}
hp_taco_device::tape_pos_t hp_taco_device::word_end_pos(const tape_track_t::iterator& it)
{
- return it->first + word_length(it->second);
+ return it->first + word_length(it->second);
}
void hp_taco_device::adjust_it(tape_track_t& track , tape_track_t::iterator& it , tape_pos_t pos)
{
- if (it != track.begin()) {
- it--;
- if (word_end_pos(it) <= pos) {
- it++;
- }
- }
+ if (it != track.begin()) {
+ it--;
+ if (word_end_pos(it) <= pos) {
+ it++;
+ }
+ }
}
// Write a word on current tape track
void hp_taco_device::write_word(tape_pos_t start , tape_word_t word , tape_pos_t& length)
{
- tape_track_t& track = current_track();
- tape_track_t::iterator it_low = track.lower_bound(start);
- adjust_it(track , it_low , start);
- length = word_length(word);
- tape_pos_t end_pos = start + length;
- tape_track_t::iterator it_high = track.lower_bound(end_pos);
+ tape_track_t& track = current_track();
+ tape_track_t::iterator it_low = track.lower_bound(start);
+ adjust_it(track , it_low , start);
+ length = word_length(word);
+ tape_pos_t end_pos = start + length;
+ tape_track_t::iterator it_high = track.lower_bound(end_pos);
- track.erase(it_low , it_high);
+ track.erase(it_low , it_high);
- track.insert(it_high , std::make_pair(start, word));
- LOG_0(("WR %04x @ T%u:%u\n" , word , BIT(m_status_reg , STATUS_TRACKB_BIT) , start));
+ track.insert(it_high , std::make_pair(start, word));
+ LOG_0(("WR %04x @ T%u:%u\n" , word , BIT(m_status_reg , STATUS_TRACKB_BIT) , start));
}
// Write a gap on current track
void hp_taco_device::write_gap(tape_pos_t a , tape_pos_t b)
{
- ensure_a_lt_b(a , b);
- tape_track_t& track = current_track();
- tape_track_t::iterator it_low = track.lower_bound(a);
- adjust_it(track , it_low , a);
- tape_track_t::iterator it_high = track.lower_bound(b);
+ ensure_a_lt_b(a , b);
+ tape_track_t& track = current_track();
+ tape_track_t::iterator it_low = track.lower_bound(a);
+ adjust_it(track , it_low , a);
+ tape_track_t::iterator it_high = track.lower_bound(b);
- track.erase(it_low, it_high);
+ track.erase(it_low, it_high);
- LOG_0(("GAP on T%u:[%u,%u)\n" , BIT(m_status_reg , STATUS_TRACKB_BIT) , a , b));
+ LOG_0(("GAP on T%u:[%u,%u)\n" , BIT(m_status_reg , STATUS_TRACKB_BIT) , a , b));
}
bool hp_taco_device::just_gap(tape_pos_t a , tape_pos_t b)
{
- ensure_a_lt_b(a , b);
- tape_track_t& track = current_track();
- tape_track_t::iterator it_low = track.lower_bound(a);
- tape_track_t::iterator it_high = track.lower_bound(b);
+ ensure_a_lt_b(a , b);
+ tape_track_t& track = current_track();
+ tape_track_t::iterator it_low = track.lower_bound(a);
+ tape_track_t::iterator it_high = track.lower_bound(b);
- adjust_it(track, it_low, a);
+ adjust_it(track, it_low, a);
- return it_low == it_high;
+ return it_low == it_high;
}
hp_taco_device::tape_pos_t hp_taco_device::farthest_end(const tape_track_t::iterator& it) const
{
- if (m_tape_fwd) {
- return word_end_pos(it);
- } else {
- return it->first;
- }
+ if (m_tape_fwd) {
+ return word_end_pos(it);
+ } else {
+ return it->first;
+ }
}
bool hp_taco_device::next_data(tape_track_t::iterator& it , tape_pos_t pos , bool inclusive)
{
- tape_track_t& track = current_track();
- it = track.lower_bound(pos);
- if (m_tape_fwd) {
- if (inclusive) {
- adjust_it(track, it, pos);
- }
- return it != track.end();
- } else {
- // Never more than 2 iterations
- do {
- if (it == track.begin()) {
- it = track.end();
- return false;
- }
- it--;
- } while (!inclusive && word_end_pos(it) > pos);
- return true;
- }
+ tape_track_t& track = current_track();
+ it = track.lower_bound(pos);
+ if (m_tape_fwd) {
+ if (inclusive) {
+ adjust_it(track, it, pos);
+ }
+ return it != track.end();
+ } else {
+ // Never more than 2 iterations
+ do {
+ if (it == track.begin()) {
+ it = track.end();
+ return false;
+ }
+ it--;
+ } while (!inclusive && word_end_pos(it) > pos);
+ return true;
+ }
}
hp_taco_device::adv_res_t hp_taco_device::adv_it(tape_track_t::iterator& it)
{
- tape_track_t& track = current_track();
- if (m_tape_fwd) {
- tape_pos_t prev_pos = word_end_pos(it);
- it++;
- if (it == track.end()) {
- return ADV_NO_MORE_DATA;
- } else {
- adv_res_t res = prev_pos == it->first ? ADV_CONT_DATA : ADV_DISCONT_DATA;
- return res;
- }
- } else {
- if (it == track.begin()) {
- it = track.end();
- return ADV_NO_MORE_DATA;
- } else {
- tape_pos_t prev_pos = it->first;
- it--;
- return prev_pos == word_end_pos(it) ? ADV_CONT_DATA : ADV_DISCONT_DATA;
- }
- }
+ tape_track_t& track = current_track();
+ if (m_tape_fwd) {
+ tape_pos_t prev_pos = word_end_pos(it);
+ it++;
+ if (it == track.end()) {
+ return ADV_NO_MORE_DATA;
+ } else {
+ adv_res_t res = prev_pos == it->first ? ADV_CONT_DATA : ADV_DISCONT_DATA;
+ return res;
+ }
+ } else {
+ if (it == track.begin()) {
+ it = track.end();
+ return ADV_NO_MORE_DATA;
+ } else {
+ tape_pos_t prev_pos = it->first;
+ it--;
+ return prev_pos == word_end_pos(it) ? ADV_CONT_DATA : ADV_DISCONT_DATA;
+ }
+ }
}
attotime hp_taco_device::fetch_next_wr_word(void)
{
- if (m_data_reg_full) {
- m_next_word = m_data_reg;
- m_data_reg_full = false;
- LOG_0(("next %04x (DR)\n" , m_next_word));
- } else {
- // When data register is empty, write checksum word
- m_next_word = m_checksum_reg;
- LOG_0(("next %04x (CS)\n" , m_next_word));
- }
- // Update checksum with new word
- m_checksum_reg += m_next_word;
-
- return time_to_distance(word_length(m_next_word));
+ if (m_data_reg_full) {
+ m_next_word = m_data_reg;
+ m_data_reg_full = false;
+ LOG_0(("next %04x (DR)\n" , m_next_word));
+ } else {
+ // When data register is empty, write checksum word
+ m_next_word = m_checksum_reg;
+ LOG_0(("next %04x (CS)\n" , m_next_word));
+ }
+ // Update checksum with new word
+ m_checksum_reg += m_next_word;
+
+ return time_to_distance(word_length(m_next_word));
}
attotime hp_taco_device::time_to_rd_next_word(tape_pos_t& word_rd_pos)
{
- if (m_rd_it_valid) {
- word_rd_pos = farthest_end(m_rd_it);
- return time_to_target(word_rd_pos);
- } else {
- return attotime::never;
- }
+ if (m_rd_it_valid) {
+ word_rd_pos = farthest_end(m_rd_it);
+ return time_to_target(word_rd_pos);
+ } else {
+ return attotime::never;
+ }
}
/**
@@ -1017,451 +1017,451 @@ attotime hp_taco_device::time_to_rd_next_word(tape_pos_t& word_rd_pos)
*/
bool hp_taco_device::next_n_gap(tape_pos_t& pos , tape_track_t::iterator it , unsigned n_gaps , tape_pos_t min_gap)
{
- tape_track_t& track = current_track();
- bool done = false;
- tape_track_t::iterator prev_it;
-
- if (m_tape_fwd) {
- tape_pos_t next_pos;
-
- while (1) {
- if (it == track.end()) {
- next_pos = TAPE_LENGTH;
- done = true;
- } else {
- next_pos = it->first;
- }
- if (((next_pos - pos) >= min_gap && --n_gaps == 0) || done) {
- break;
- }
- adv_res_t adv_res;
- do {
- prev_it = it;
- adv_res = adv_it(it);
- } while (adv_res == ADV_CONT_DATA);
- pos = word_end_pos(prev_it);
- }
- } else {
- tape_pos_t next_pos;
-
- while (1) {
- if (it == track.end()) {
- next_pos = 0;
- done = true;
- } else {
- next_pos = word_end_pos(it);
- }
- if (((pos - next_pos) >= min_gap && --n_gaps == 0) || done) {
- break;
- }
- adv_res_t adv_res;
- do {
- prev_it = it;
- adv_res = adv_it(it);
- } while (adv_res == ADV_CONT_DATA);
- pos = prev_it->first;
- }
- }
-
- // Set "pos" where minimum gap size is met
- pos_offset(pos , min_gap);
-
- return n_gaps == 0;
+ tape_track_t& track = current_track();
+ bool done = false;
+ tape_track_t::iterator prev_it;
+
+ if (m_tape_fwd) {
+ tape_pos_t next_pos;
+
+ while (1) {
+ if (it == track.end()) {
+ next_pos = TAPE_LENGTH;
+ done = true;
+ } else {
+ next_pos = it->first;
+ }
+ if (((next_pos - pos) >= min_gap && --n_gaps == 0) || done) {
+ break;
+ }
+ adv_res_t adv_res;
+ do {
+ prev_it = it;
+ adv_res = adv_it(it);
+ } while (adv_res == ADV_CONT_DATA);
+ pos = word_end_pos(prev_it);
+ }
+ } else {
+ tape_pos_t next_pos;
+
+ while (1) {
+ if (it == track.end()) {
+ next_pos = 0;
+ done = true;
+ } else {
+ next_pos = word_end_pos(it);
+ }
+ if (((pos - next_pos) >= min_gap && --n_gaps == 0) || done) {
+ break;
+ }
+ adv_res_t adv_res;
+ do {
+ prev_it = it;
+ adv_res = adv_it(it);
+ } while (adv_res == ADV_CONT_DATA);
+ pos = prev_it->first;
+ }
+ }
+
+ // Set "pos" where minimum gap size is met
+ pos_offset(pos , min_gap);
+
+ return n_gaps == 0;
}
bool hp_taco_device::next_n_gap(tape_pos_t& pos , unsigned n_gaps , tape_pos_t min_gap)
{
- tape_track_t::iterator it;
- // First align with next data
- next_data(it, pos, true);
- // Then scan for n_gaps
- return next_n_gap(pos, it, n_gaps, min_gap);
+ tape_track_t::iterator it;
+ // First align with next data
+ next_data(it, pos, true);
+ // Then scan for n_gaps
+ return next_n_gap(pos, it, n_gaps, min_gap);
}
void hp_taco_device::clear_tape(void)
{
- for (unsigned track_n = 0; track_n < 2; track_n++) {
- m_tracks[ track_n ].clear();
- }
+ for (unsigned track_n = 0; track_n < 2; track_n++) {
+ m_tracks[ track_n ].clear();
+ }
}
void hp_taco_device::dump_sequence(tape_track_t::const_iterator it_start , unsigned n_words)
{
- if (n_words) {
- UINT32 tmp32;
- UINT16 tmp16;
-
- tmp32 = n_words;
- fwrite(&tmp32 , sizeof(tmp32));
- tmp32 = it_start->first;
- fwrite(&tmp32 , sizeof(tmp32));
-
- for (unsigned i = 0; i < n_words; i++) {
- tmp16 = it_start->second;
- fwrite(&tmp16 , sizeof(tmp16));
- it_start++;
- }
- }
+ if (n_words) {
+ UINT32 tmp32;
+ UINT16 tmp16;
+
+ tmp32 = n_words;
+ fwrite(&tmp32 , sizeof(tmp32));
+ tmp32 = it_start->first;
+ fwrite(&tmp32 , sizeof(tmp32));
+
+ for (unsigned i = 0; i < n_words; i++) {
+ tmp16 = it_start->second;
+ fwrite(&tmp16 , sizeof(tmp16));
+ it_start++;
+ }
+ }
}
void hp_taco_device::save_tape(void)
{
- UINT32 tmp32;
-
- fseek(0, SEEK_SET);
-
- tmp32 = FILE_MAGIC;
- fwrite(&tmp32 , sizeof(tmp32));
-
- for (unsigned track_n = 0; track_n < 2; track_n++) {
- const tape_track_t& track = m_tracks[ track_n ];
- tape_pos_t next_pos = (tape_pos_t)-1;
- unsigned n_words = 0;
- tape_track_t::const_iterator it_start;
- for (tape_track_t::const_iterator it = track.cbegin(); it != track.cend(); it++) {
- if (it->first != next_pos) {
- dump_sequence(it_start , n_words);
- it_start = it;
- n_words = 0;
- }
- next_pos = it->first + word_length(it->second);
- n_words++;
- }
- dump_sequence(it_start , n_words);
- // End of track
- tmp32 = (UINT32)-1;
- fwrite(&tmp32 , sizeof(tmp32));
- }
+ UINT32 tmp32;
+
+ fseek(0, SEEK_SET);
+
+ tmp32 = FILE_MAGIC;
+ fwrite(&tmp32 , sizeof(tmp32));
+
+ for (unsigned track_n = 0; track_n < 2; track_n++) {
+ const tape_track_t& track = m_tracks[ track_n ];
+ tape_pos_t next_pos = (tape_pos_t)-1;
+ unsigned n_words = 0;
+ tape_track_t::const_iterator it_start;
+ for (tape_track_t::const_iterator it = track.cbegin(); it != track.cend(); it++) {
+ if (it->first != next_pos) {
+ dump_sequence(it_start , n_words);
+ it_start = it;
+ n_words = 0;
+ }
+ next_pos = it->first + word_length(it->second);
+ n_words++;
+ }
+ dump_sequence(it_start , n_words);
+ // End of track
+ tmp32 = (UINT32)-1;
+ fwrite(&tmp32 , sizeof(tmp32));
+ }
}
bool hp_taco_device::load_track(tape_track_t& track)
{
- UINT32 tmp32;
+ UINT32 tmp32;
- track.clear();
+ track.clear();
- while (1) {
- if (fread(&tmp32 , sizeof(tmp32)) != sizeof(tmp32)) {
- return false;
- }
+ while (1) {
+ if (fread(&tmp32 , sizeof(tmp32)) != sizeof(tmp32)) {
+ return false;
+ }
- if (tmp32 == (UINT32)-1) {
- return true;
- }
+ if (tmp32 == (UINT32)-1) {
+ return true;
+ }
- unsigned n_words = tmp32;
+ unsigned n_words = tmp32;
- if (fread(&tmp32 , sizeof(tmp32)) != sizeof(tmp32)) {
- return false;
- }
+ if (fread(&tmp32 , sizeof(tmp32)) != sizeof(tmp32)) {
+ return false;
+ }
- tape_pos_t pos = (tape_pos_t)tmp32;
+ tape_pos_t pos = (tape_pos_t)tmp32;
- for (unsigned i = 0; i < n_words; i++) {
- UINT16 tmp16;
+ for (unsigned i = 0; i < n_words; i++) {
+ UINT16 tmp16;
- if (fread(&tmp16 , sizeof(tmp16)) != sizeof(tmp16)) {
- return false;
- }
+ if (fread(&tmp16 , sizeof(tmp16)) != sizeof(tmp16)) {
+ return false;
+ }
- track.insert(std::make_pair(pos , tmp16));
- pos += word_length(tmp16);
- }
- }
+ track.insert(std::make_pair(pos , tmp16));
+ pos += word_length(tmp16);
+ }
+ }
}
bool hp_taco_device::load_tape(void)
{
- UINT32 magic;
-
- if (fread(&magic , sizeof(magic)) != sizeof(magic) ||
- magic != FILE_MAGIC) {
- return false;
- }
-
- for (unsigned track_n = 0; track_n < 2; track_n++) {
- if (!load_track(m_tracks[ track_n ])) {
- LOG(("load_tape failed"));
- clear_tape();
- return false;
- }
- }
-
- LOG(("load_tape done\n"));
- return true;
+ UINT32 magic;
+
+ if (fread(&magic , sizeof(magic)) != sizeof(magic) ||
+ magic != FILE_MAGIC) {
+ return false;
+ }
+
+ for (unsigned track_n = 0; track_n < 2; track_n++) {
+ if (!load_track(m_tracks[ track_n ])) {
+ LOG(("load_tape failed"));
+ clear_tape();
+ return false;
+ }
+ }
+
+ LOG(("load_tape done\n"));
+ return true;
}
void hp_taco_device::set_tape_present(bool present)
{
- if (present) {
- if (is_readonly()) {
- BIT_SET(m_status_reg, STATUS_WPR_BIT);
- } else {
- BIT_CLR(m_status_reg, STATUS_WPR_BIT);
- }
- // STATUS_CART_OUT_BIT is reset by CMD_CLEAR
- } else {
- BIT_SET(m_status_reg, STATUS_CART_OUT_BIT);
- BIT_SET(m_status_reg, STATUS_WPR_BIT);
- }
+ if (present) {
+ if (is_readonly()) {
+ BIT_SET(m_status_reg, STATUS_WPR_BIT);
+ } else {
+ BIT_CLR(m_status_reg, STATUS_WPR_BIT);
+ }
+ // STATUS_CART_OUT_BIT is reset by CMD_CLEAR
+ } else {
+ BIT_SET(m_status_reg, STATUS_CART_OUT_BIT);
+ BIT_SET(m_status_reg, STATUS_WPR_BIT);
+ }
}
attotime hp_taco_device::time_to_next_hole(void) const
{
- return time_to_target(next_hole());
+ return time_to_target(next_hole());
}
attotime hp_taco_device::time_to_tach_pulses(void) const
{
- return time_to_distance((tape_pos_t)(0x10000U - m_tach_reg) * TAPE_POS_FRACT);
+ return time_to_distance((tape_pos_t)(0x10000U - m_tach_reg) * TAPE_POS_FRACT);
}
void hp_taco_device::start_cmd_exec(UINT16 new_cmd_reg)
{
- LOG(("Cmd = %02x\n" , CMD_CODE(new_cmd_reg)));
-
- update_tape_pos();
-
- attotime cmd_duration = attotime::never;
- attotime time_to_hole = attotime::never;
-
- unsigned new_cmd_code = CMD_CODE(new_cmd_reg);
-
- if (new_cmd_code != CMD_START_READ &&
- new_cmd_code != CMD_END_READ &&
- new_cmd_code != CMD_CLEAR) {
- m_rd_it_valid = false;
- }
-
- switch (new_cmd_code) {
- case CMD_INDTA_INGAP:
- // Errors: CART OUT,FAST SPEED
- if (start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK)) {
- m_cmd_state = 0;
- if (next_data(m_rd_it , m_tape_pos , true)) {
- cmd_duration = time_to_target(farthest_end(m_rd_it));
- }
- }
- break;
-
- case CMD_FINAL_GAP:
- // Errors: WP,CART OUT
- if (start_tape_cmd(new_cmd_reg , 0 , STATUS_WPR_MASK)) {
- m_rw_pos = m_tape_pos;
- cmd_duration = time_to_distance(END_GAP_LENGTH);
- time_to_hole = time_to_next_hole();
- }
- break;
-
- case CMD_CLEAR:
- set_error(false);
- BIT_CLR(m_status_reg, STATUS_HOLE_BIT);
- BIT_CLR(m_status_reg, STATUS_CART_OUT_BIT);
- BIT_CLR(m_status_reg, STATUS_WPR_BIT);
- set_tape_present(is_loaded());
- // This is a special command: it doesn't raise IRQ at completion and it
- // doesn't replace current command
- return;
-
- case CMD_NOT_INDTA:
- // Errors: CART OUT,FAST SPEED
- if (start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK)) {
- tape_pos_t target = m_tape_pos;
- if (next_n_gap(target, 1, NO_DATA_GAP)) {
- LOG_0(("End of data @%d\n" , target));
- cmd_duration = time_to_target(target);
- }
- // Holes detected?
- }
- break;
-
- case CMD_INIT_WRITE:
- // Errors: WP,CART OUT,fast speed,reverse
- if (start_tape_cmd(new_cmd_reg , DIR_FWD_MASK , STATUS_WPR_MASK | SPEED_FAST_MASK)) {
- m_next_word = PREAMBLE_WORD;
- m_rw_pos = m_tape_pos;
- cmd_duration = time_to_distance(word_length(m_next_word));
- }
- break;
-
- case CMD_STOP:
- if (CMD_CODE(m_cmd_reg) != CMD_STOP) {
- if (m_start_time.is_never()) {
- // Tape is already stopped
- cmd_duration = attotime::from_usec(QUICK_CMD_USEC);
- } else {
- // Start braking timer
- cmd_duration = attotime::from_msec(m_tape_fast ? FAST_BRAKE_MSEC : SLOW_BRAKE_MSEC);
- }
- m_cmd_reg = new_cmd_reg;
- } else {
- // TODO: check if ok
- return;
- }
- break;
-
- case CMD_SET_TRACK:
- // Don't know if this command really starts the tape or not (probably it doesn't)
- if (start_tape_cmd(new_cmd_reg , 0 , 0)) {
- // When b9 is 0, set track A/B
- // When b9 is 1, ignore command (in TACO chip it has an unknown purpose)
- if (!UNKNOWN_B9(new_cmd_reg)) {
- if (CMD_OPT(new_cmd_reg)) {
- BIT_SET(m_status_reg, STATUS_TRACKB_BIT);
- } else {
- BIT_CLR(m_status_reg, STATUS_TRACKB_BIT);
- }
- }
- cmd_duration = attotime::from_usec(QUICK_CMD_USEC);
- }
- break;
-
- case CMD_MOVE:
- if (start_tape_cmd(new_cmd_reg , 0 , 0)) {
- time_to_hole = time_to_next_hole();
- }
- break;
-
- case CMD_INGAP_MOVE:
- // Errors: CART OUT,FAST SPEED
- if (start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK)) {
- m_cmd_state = 0;
- tape_pos_t target = m_tape_pos;
- if (next_n_gap(target, 1, MIN_IRG_LENGTH)) {
- LOG_0(("IRG @%d\n" , target));
- cmd_duration = time_to_target(target);
- }
- // Holes detected?
- }
- break;
-
- case CMD_WRITE_IRG:
- // Errors: WP,CART OUT
- if (start_tape_cmd(new_cmd_reg , 0 , STATUS_WPR_MASK)) {
- m_rw_pos = m_tape_pos;
- cmd_duration = time_to_tach_pulses();
- time_to_hole = time_to_next_hole();
- }
- break;
-
- case CMD_SCAN_RECORDS:
- // Errors: CART OUT
- if (start_tape_cmd(new_cmd_reg , 0 , 0)) {
- m_cmd_state = 0;
- if (next_data(m_rd_it , m_tape_pos , true)) {
- cmd_duration = time_to_target(farthest_end(m_rd_it));
- }
- time_to_hole = time_to_next_hole();
- }
- break;
-
- case CMD_RECORD_WRITE:
- // Errors: WP,CART OUT,fast speed,reverse
- if (start_tape_cmd(new_cmd_reg , DIR_FWD_MASK , STATUS_WPR_MASK | SPEED_FAST_MASK)) {
- // Search for preamble first
- m_cmd_state = 0;
- m_rd_it_valid = next_data(m_rd_it , m_tape_pos , false);
- cmd_duration = time_to_rd_next_word(m_rw_pos);
- // Holes detected?
- }
- break;
-
- case CMD_MOVE_INDTA:
- // Errors: CART OUT,FAST SPEED
- if (start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK)) {
- m_cmd_state = 0;
- cmd_duration = time_to_tach_pulses();
- // Holes detected?
- }
- break;
-
- case CMD_UNK_1b:
- if (start_tape_cmd(new_cmd_reg , 0 , 0)) {
- // Unknown purpose, but make it a NOP (it's used in "T" test of test ROM)
- cmd_duration = attotime::from_usec(QUICK_CMD_USEC);
- }
- break;
-
- case CMD_DELTA_MOVE_HOLE:
- case CMD_DELTA_MOVE_IRG:
- if (start_tape_cmd(new_cmd_reg , 0 , 0)) {
- cmd_duration = time_to_tach_pulses();
- time_to_hole = time_to_next_hole();
- }
- break;
-
- case CMD_START_READ:
- // Yes, you can read tape backwards: test "C" does that!
- // Because of this DIR_FWD_MASK is not in the "must be 1" mask.
- if (start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK)) {
- // TODO: check anche m_rw_pos sforato
- if (!m_rd_it_valid) {
- // Search for preamble first
- m_cmd_state = 0;
- m_rd_it_valid = next_data(m_rd_it , m_tape_pos , false);
- }
-
- cmd_duration = time_to_rd_next_word(m_rw_pos);
- time_to_hole = time_to_next_hole();
- }
- break;
-
- case CMD_END_READ:
- // This command only makes sense after CMD_START_READ
- if (CMD_CODE(m_cmd_reg) == CMD_START_READ && m_cmd_state == 1 &&
- start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK)) {
- LOG_0(("END_READ %d\n" , m_rd_it_valid));
- cmd_duration = time_to_rd_next_word(m_rw_pos);
- time_to_hole = time_to_next_hole();
- }
- break;
-
- default:
- LOG(("Unrecognized command\n"));
- break;
- }
-
- m_tape_timer->adjust(cmd_duration);
- m_hole_timer->adjust(time_to_hole);
+ LOG(("Cmd = %02x\n" , CMD_CODE(new_cmd_reg)));
+
+ update_tape_pos();
+
+ attotime cmd_duration = attotime::never;
+ attotime time_to_hole = attotime::never;
+
+ unsigned new_cmd_code = CMD_CODE(new_cmd_reg);
+
+ if (new_cmd_code != CMD_START_READ &&
+ new_cmd_code != CMD_END_READ &&
+ new_cmd_code != CMD_CLEAR) {
+ m_rd_it_valid = false;
+ }
+
+ switch (new_cmd_code) {
+ case CMD_INDTA_INGAP:
+ // Errors: CART OUT,FAST SPEED
+ if (start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK)) {
+ m_cmd_state = 0;
+ if (next_data(m_rd_it , m_tape_pos , true)) {
+ cmd_duration = time_to_target(farthest_end(m_rd_it));
+ }
+ }
+ break;
+
+ case CMD_FINAL_GAP:
+ // Errors: WP,CART OUT
+ if (start_tape_cmd(new_cmd_reg , 0 , STATUS_WPR_MASK)) {
+ m_rw_pos = m_tape_pos;
+ cmd_duration = time_to_distance(END_GAP_LENGTH);
+ time_to_hole = time_to_next_hole();
+ }
+ break;
+
+ case CMD_CLEAR:
+ set_error(false);
+ BIT_CLR(m_status_reg, STATUS_HOLE_BIT);
+ BIT_CLR(m_status_reg, STATUS_CART_OUT_BIT);
+ BIT_CLR(m_status_reg, STATUS_WPR_BIT);
+ set_tape_present(is_loaded());
+ // This is a special command: it doesn't raise IRQ at completion and it
+ // doesn't replace current command
+ return;
+
+ case CMD_NOT_INDTA:
+ // Errors: CART OUT,FAST SPEED
+ if (start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK)) {
+ tape_pos_t target = m_tape_pos;
+ if (next_n_gap(target, 1, NO_DATA_GAP)) {
+ LOG_0(("End of data @%d\n" , target));
+ cmd_duration = time_to_target(target);
+ }
+ // Holes detected?
+ }
+ break;
+
+ case CMD_INIT_WRITE:
+ // Errors: WP,CART OUT,fast speed,reverse
+ if (start_tape_cmd(new_cmd_reg , DIR_FWD_MASK , STATUS_WPR_MASK | SPEED_FAST_MASK)) {
+ m_next_word = PREAMBLE_WORD;
+ m_rw_pos = m_tape_pos;
+ cmd_duration = time_to_distance(word_length(m_next_word));
+ }
+ break;
+
+ case CMD_STOP:
+ if (CMD_CODE(m_cmd_reg) != CMD_STOP) {
+ if (m_start_time.is_never()) {
+ // Tape is already stopped
+ cmd_duration = attotime::from_usec(QUICK_CMD_USEC);
+ } else {
+ // Start braking timer
+ cmd_duration = attotime::from_msec(m_tape_fast ? FAST_BRAKE_MSEC : SLOW_BRAKE_MSEC);
+ }
+ m_cmd_reg = new_cmd_reg;
+ } else {
+ // TODO: check if ok
+ return;
+ }
+ break;
+
+ case CMD_SET_TRACK:
+ // Don't know if this command really starts the tape or not (probably it doesn't)
+ if (start_tape_cmd(new_cmd_reg , 0 , 0)) {
+ // When b9 is 0, set track A/B
+ // When b9 is 1, ignore command (in TACO chip it has an unknown purpose)
+ if (!UNKNOWN_B9(new_cmd_reg)) {
+ if (CMD_OPT(new_cmd_reg)) {
+ BIT_SET(m_status_reg, STATUS_TRACKB_BIT);
+ } else {
+ BIT_CLR(m_status_reg, STATUS_TRACKB_BIT);
+ }
+ }
+ cmd_duration = attotime::from_usec(QUICK_CMD_USEC);
+ }
+ break;
+
+ case CMD_MOVE:
+ if (start_tape_cmd(new_cmd_reg , 0 , 0)) {
+ time_to_hole = time_to_next_hole();
+ }
+ break;
+
+ case CMD_INGAP_MOVE:
+ // Errors: CART OUT,FAST SPEED
+ if (start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK)) {
+ m_cmd_state = 0;
+ tape_pos_t target = m_tape_pos;
+ if (next_n_gap(target, 1, MIN_IRG_LENGTH)) {
+ LOG_0(("IRG @%d\n" , target));
+ cmd_duration = time_to_target(target);
+ }
+ // Holes detected?
+ }
+ break;
+
+ case CMD_WRITE_IRG:
+ // Errors: WP,CART OUT
+ if (start_tape_cmd(new_cmd_reg , 0 , STATUS_WPR_MASK)) {
+ m_rw_pos = m_tape_pos;
+ cmd_duration = time_to_tach_pulses();
+ time_to_hole = time_to_next_hole();
+ }
+ break;
+
+ case CMD_SCAN_RECORDS:
+ // Errors: CART OUT
+ if (start_tape_cmd(new_cmd_reg , 0 , 0)) {
+ m_cmd_state = 0;
+ if (next_data(m_rd_it , m_tape_pos , true)) {
+ cmd_duration = time_to_target(farthest_end(m_rd_it));
+ }
+ time_to_hole = time_to_next_hole();
+ }
+ break;
+
+ case CMD_RECORD_WRITE:
+ // Errors: WP,CART OUT,fast speed,reverse
+ if (start_tape_cmd(new_cmd_reg , DIR_FWD_MASK , STATUS_WPR_MASK | SPEED_FAST_MASK)) {
+ // Search for preamble first
+ m_cmd_state = 0;
+ m_rd_it_valid = next_data(m_rd_it , m_tape_pos , false);
+ cmd_duration = time_to_rd_next_word(m_rw_pos);
+ // Holes detected?
+ }
+ break;
+
+ case CMD_MOVE_INDTA:
+ // Errors: CART OUT,FAST SPEED
+ if (start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK)) {
+ m_cmd_state = 0;
+ cmd_duration = time_to_tach_pulses();
+ // Holes detected?
+ }
+ break;
+
+ case CMD_UNK_1b:
+ if (start_tape_cmd(new_cmd_reg , 0 , 0)) {
+ // Unknown purpose, but make it a NOP (it's used in "T" test of test ROM)
+ cmd_duration = attotime::from_usec(QUICK_CMD_USEC);
+ }
+ break;
+
+ case CMD_DELTA_MOVE_HOLE:
+ case CMD_DELTA_MOVE_IRG:
+ if (start_tape_cmd(new_cmd_reg , 0 , 0)) {
+ cmd_duration = time_to_tach_pulses();
+ time_to_hole = time_to_next_hole();
+ }
+ break;
+
+ case CMD_START_READ:
+ // Yes, you can read tape backwards: test "C" does that!
+ // Because of this DIR_FWD_MASK is not in the "must be 1" mask.
+ if (start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK)) {
+ // TODO: check anche m_rw_pos sforato
+ if (!m_rd_it_valid) {
+ // Search for preamble first
+ m_cmd_state = 0;
+ m_rd_it_valid = next_data(m_rd_it , m_tape_pos , false);
+ }
+
+ cmd_duration = time_to_rd_next_word(m_rw_pos);
+ time_to_hole = time_to_next_hole();
+ }
+ break;
+
+ case CMD_END_READ:
+ // This command only makes sense after CMD_START_READ
+ if (CMD_CODE(m_cmd_reg) == CMD_START_READ && m_cmd_state == 1 &&
+ start_tape_cmd(new_cmd_reg , 0 , SPEED_FAST_MASK)) {
+ LOG_0(("END_READ %d\n" , m_rd_it_valid));
+ cmd_duration = time_to_rd_next_word(m_rw_pos);
+ time_to_hole = time_to_next_hole();
+ }
+ break;
+
+ default:
+ LOG(("Unrecognized command\n"));
+ break;
+ }
+
+ m_tape_timer->adjust(cmd_duration);
+ m_hole_timer->adjust(time_to_hole);
}
bool hp_taco_device::call_load()
{
- LOG(("call_load %d\n" , has_been_created()));
- if (has_been_created()) {
- clear_tape();
- save_tape();
- } else if (!load_tape()) {
- seterror(IMAGE_ERROR_INVALIDIMAGE , "Wrong format");
- set_tape_present(false);
- return IMAGE_INIT_FAIL;
- }
-
- m_image_dirty = false;
-
- set_tape_present(true);
+ LOG(("call_load %d\n" , has_been_created()));
+ if (has_been_created()) {
+ clear_tape();
+ save_tape();
+ } else if (!load_tape()) {
+ seterror(IMAGE_ERROR_INVALIDIMAGE , "Wrong format");
+ set_tape_present(false);
+ return IMAGE_INIT_FAIL;
+ }
+
+ m_image_dirty = false;
+
+ set_tape_present(true);
return IMAGE_INIT_PASS;
}
bool hp_taco_device::call_create(int format_type, option_resolution *format_options)
{
- LOG(("call_create %d\n" , has_been_created()));
- return call_load();
+ LOG(("call_create %d\n" , has_been_created()));
+ return call_load();
}
void hp_taco_device::call_unload()
{
- LOG(("call_unload dirty=%d\n" , m_image_dirty));
- if (m_image_dirty) {
- save_tape();
- m_image_dirty = false;
- }
-
- clear_tape();
- set_tape_present(false);
+ LOG(("call_unload dirty=%d\n" , m_image_dirty));
+ if (m_image_dirty) {
+ save_tape();
+ m_image_dirty = false;
+ }
+
+ clear_tape();
+ set_tape_present(false);
}
const char *hp_taco_device::file_extensions() const
{
- return "hti";
+ return "hti";
}