diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 1b746fb59bc..bb630af1e5c 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -1452,7 +1452,7 @@ end if (CPUS["PATINHOFEIO"]~=null) then files { MAME_DIR .. "src/devices/cpu/patinhofeio/patinho_feio.cpp", - MAME_DIR .. "src/devices/cpu/patinhofeio/patinhofeio_cpu.h", + MAME_DIR .. "src/devices/cpu/patinhofeio/patinho_feio.h", } end diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 415a39f1897..13898021fd6 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -2894,7 +2894,6 @@ files { createMESSProjects(_target, _subtarget, "usp") files { MAME_DIR .. "src/mame/drivers/patinho_feio.cpp", - MAME_DIR .. "src/mame/includes/patinho_feio.h", } createMESSProjects(_target, _subtarget, "veb") diff --git a/src/devices/cpu/patinhofeio/patinho_feio.cpp b/src/devices/cpu/patinhofeio/patinho_feio.cpp index 8482db59c41..78fc92a8270 100644 --- a/src/devices/cpu/patinhofeio/patinho_feio.cpp +++ b/src/devices/cpu/patinhofeio/patinho_feio.cpp @@ -1,17 +1,15 @@ // license:GPL-2.0+ // copyright-holders:Felipe Sanches /* - CPU emulation for Patinho Feio, the first computer designed and manufactured in Brazil + CPU emulation for Patinho Feio, the first computer designed and manufactured in Brazil */ #include "emu.h" #include "debugger.h" -#include "patinhofeio_cpu.h" -#include "includes/patinhofeio.h" +#include "patinho_feio.h" -#define PC m_pc //The program counter is called "contador de instrucoes" (IC) in portuguese +#define PC m_pc //The program counter is called "contador de instrucoes" in portuguese #define ACC m_acc -#define EXT m_ext #define RC read_panel_keys_register() #define FLAGS m_flags @@ -26,31 +24,23 @@ #define READ_INDEX_REG() READ_BYTE_PATINHO(0x000) #define WRITE_INDEX_REG(V) { WRITE_BYTE_PATINHO(0x000, V); m_idx = V; } -#define READ_ACC_EXTENSION_REG() READ_BYTE_PATINHO(0x001) -#define WRITE_ACC_EXTENSION_REG(V) { WRITE_BYTE_PATINHO(0x001, V); m_ext = V; } - #define ADDRESS_MASK_4K 0xFFF #define INCREMENT_PC_4K (PC = (PC+1) & ADDRESS_MASK_4K) -void patinho_feio_cpu_device::set_flag(UINT8 flag, bool state){ - if (state){ - FLAGS |= flag; - } else { - FLAGS &= ~flag; - } -} - -void patinho_feio_cpu_device::compute_effective_address(unsigned int addr){ - m_addr = addr; +unsigned int patinho_feio_cpu_device::compute_effective_address(unsigned int addr){ + unsigned int retval = addr; if (m_indirect_addressing){ - m_addr = READ_WORD_PATINHO(m_addr); - if (m_addr & 0x1000) - compute_effective_address(m_addr & 0xFFF); + retval = READ_WORD_PATINHO(addr); + if (retval & 0x1000) + return compute_effective_address(retval & 0xFFF); } + + return retval; } const device_type PATINHO_FEIO = &device_creator; + //Internal 4kbytes of RAM static ADDRESS_MAP_START(prog_8bit, AS_PROGRAM, 8, patinho_feio_cpu_device) AM_RANGE(0x0000, 0x0fff) AM_RAM AM_SHARE("internalram") @@ -60,12 +50,7 @@ patinho_feio_cpu_device::patinho_feio_cpu_device(const machine_config &mconfig, : cpu_device(mconfig, PATINHO_FEIO, "PATINHO FEIO", tag, owner, clock, "patinho_feio_cpu", __FILE__), m_program_config("program", ENDIANNESS_LITTLE, 8, 12, 0, ADDRESS_MAP_NAME(prog_8bit)), m_icount(0), - m_rc_read_cb(*this), - m_buttons_read_cb(*this), - /* These arrays of *this are very ugly. I wonder if there's a better way of coding this... */ - m_iodev_read_cb{*this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this}, - m_iodev_write_cb{*this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this}, - m_iodev_status_cb{*this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this, *this} + m_rc_read_cb(*this) { } @@ -78,43 +63,20 @@ UINT16 patinho_feio_cpu_device::read_panel_keys_register(){ return m_rc; } -void patinho_feio_cpu_device::transfer_byte_from_external_device(UINT8 channel, UINT8 data){ - m_iodev_incoming_byte[channel] = data; - m_iodev_status[channel] = IODEV_READY; - m_iodev_control[channel] = NO_REQUEST; -} - void patinho_feio_cpu_device::device_start() { m_program = &space(AS_PROGRAM); -//TODO: implement handling of these special purpose registers -// which are also mapped to the first few main memory positions: -// -// ERI: "Endereço de Retorno de Interrupção" -// "Interrupt Return Address" -// stored at addresses 002 and 003 -// -// ETI: "início de uma rotina de tratamento de interrupção (se houver)" -// "start of an interrupt service routine (if any)" -// stored at address 004 (and 005 as well?) -// -// It seems that the general purpose memory starts at address 006. - save_item(NAME(m_pc)); save_item(NAME(m_acc)); - save_item(NAME(m_ext)); save_item(NAME(m_rc)); save_item(NAME(m_idx)); save_item(NAME(m_flags)); - save_item(NAME(m_addr)); - save_item(NAME(m_opcode)); // Register state for debugger state_add( PATINHO_FEIO_CI, "CI", m_pc ).mask(0xFFF); state_add( PATINHO_FEIO_RC, "RC", m_rc ).mask(0xFFF); state_add( PATINHO_FEIO_ACC, "ACC", m_acc ).mask(0xFF); - state_add( PATINHO_FEIO_EXT, "EXT", m_ext ).mask(0xFF); state_add( PATINHO_FEIO_IDX, "IDX", m_idx ).mask(0xFF); state_add(STATE_GENPC, "GENPC", m_pc).formatstr("0%06O").noshow(); state_add(STATE_GENFLAGS, "GENFLAGS", m_flags).noshow().formatstr("%8s"); @@ -125,72 +87,32 @@ void patinho_feio_cpu_device::device_start() m_rc_read_cb.resolve(); } - if (!m_buttons_read_cb.isnull()){ - m_buttons_read_cb.resolve(); - } - - for (int i=0; i<16; i++){ - if (!m_iodev_read_cb[i].isnull()) - m_iodev_read_cb[i].resolve(); - if (!m_iodev_write_cb[i].isnull()) - m_iodev_write_cb[i].resolve(); - } - m_icountptr = &m_icount; } void patinho_feio_cpu_device::device_reset() { - m_pc = 0; - //m_pc = 0x006; //"PATINHO FEIO" hello-world - //m_pc = 0x010; //micro-pre-loader - //m_pc = 0xE00; //HEXAM - m_rc = 0; + m_pc = 0x006; m_acc = 0; - m_ext = READ_ACC_EXTENSION_REG(); + m_rc = 0; m_idx = READ_INDEX_REG(); m_flags = 0; - m_run = false; + m_run = true; m_scheduled_IND_bit_reset = false; m_indirect_addressing = false; - m_addr = 0; - m_opcode = 0; - m_mode = ADDRESSING_MODE; - ((patinho_feio_state*) owner())->update_panel(ACC, m_opcode, READ_BYTE_PATINHO(m_addr), m_addr, PC, FLAGS, RC, m_mode); } /* execute instructions on this CPU until icount expires */ -void patinho_feio_cpu_device::execute_run() { - do { - read_panel_keys_register(); - m_ext = READ_ACC_EXTENSION_REG(); - m_idx = READ_INDEX_REG(); - ((patinho_feio_state*) owner())->update_panel(ACC, READ_BYTE_PATINHO(PC), READ_BYTE_PATINHO(m_addr), m_addr, PC, FLAGS, RC, m_mode); - debugger_instruction_hook(this, PC); - - if (!m_run){ - if (!m_buttons_read_cb.isnull()){ - UINT16 buttons = m_buttons_read_cb(0); - if (buttons & BUTTON_PARTIDA){ - /* "startup" button */ - switch (m_mode){ - case ADDRESSING_MODE: PC = RC; break; - case NORMAL_MODE: m_run = true; break; - case DATA_STORE_MODE: WRITE_BYTE_PATINHO(PC, RC & 0xFF); break; //TODO: we also need RE (address register, instead of using PC directly) - /*TODO: case DATA_VIEW_MODE: RD = READ_BYTE_PATINHO(RC); break; //we need to implement RD (the 'data register') */ - default: break; - } - } - if (buttons & BUTTON_NORMAL) m_mode = NORMAL_MODE; - if (buttons & BUTTON_ENDERECAMENTO) m_mode = ADDRESSING_MODE; - if (buttons & BUTTON_EXPOSICAO) m_mode = DATA_VIEW_MODE; - if (buttons & BUTTON_ARMAZENAMENTO) m_mode = DATA_STORE_MODE; - if (buttons & BUTTON_CICLO_UNICO) m_mode = CYCLE_STEP_MODE; - if (buttons & BUTTON_INSTRUCAO_UNICA) m_mode = INSTRUCTION_STEP_MODE; - if (buttons & BUTTON_PREPARACAO) device_reset(); - } +void patinho_feio_cpu_device::execute_run() +{ + do + { + if ((! m_run)){ m_icount = 0; /* if processor is stopped, just burn cycles */ } else { + m_idx = READ_INDEX_REG(); + read_panel_keys_register(); + execute_instruction(); m_icount --; } @@ -201,10 +123,12 @@ void patinho_feio_cpu_device::execute_run() { /* execute one instruction */ void patinho_feio_cpu_device::execute_instruction() { + debugger_instruction_hook(this, PC); + offs_t addr; bool skip; unsigned int tmp; unsigned char value, channel, function; - m_opcode = READ_BYTE_PATINHO(PC); + unsigned char opcode = READ_BYTE_PATINHO(PC); INCREMENT_PC_4K; if (m_scheduled_IND_bit_reset) @@ -213,7 +137,7 @@ void patinho_feio_cpu_device::execute_instruction() if (m_indirect_addressing) m_scheduled_IND_bit_reset = true; - switch (m_opcode){ + switch (opcode){ case 0xD2: //XOR: Computes the bitwise XOR of an immediate into the accumulator ACC ^= READ_BYTE_PATINHO(PC); @@ -229,10 +153,9 @@ void patinho_feio_cpu_device::execute_instruction() case 0xD8: //SOMI="Soma Imediato": // Add an immediate into the accumulator - set_flag(V, ((((INT16) ACC) + ((INT16) READ_BYTE_PATINHO(PC))) >> 8)); - set_flag(T, ((((INT8) (ACC & 0x7F)) + ((INT8) (READ_BYTE_PATINHO(PC) & 0x7F))) >> 7) == V); ACC += READ_BYTE_PATINHO(PC); INCREMENT_PC_4K; + //TODO: update T and V flags return; case 0xDA: //CARI="Carrega Imediato": @@ -330,79 +253,6 @@ void patinho_feio_cpu_device::execute_instruction() ACC = (RC & 0xFF); FLAGS = V; return; - case 0x90: - //ST 0 = "Se T=0, Pula" - // If T is zero, skip the next instruction - if ((FLAGS & T) == 0) - INCREMENT_PC_4K; //skip - return; - case 0x91: - //STM 0 = "Se T=0, Pula e muda" - // If T is zero, skip the next instruction - // and toggle T. - if ((FLAGS & T) == 0){ - INCREMENT_PC_4K; //skip - FLAGS |= T; //set T=1 - } - return; - case 0x92: - //ST 1 = "Se T=1, Pula" - // If T is one, skip the next instruction - if ((FLAGS & T) == 1) - INCREMENT_PC_4K; //skip - return; - case 0x93: - //STM 1 = "Se T=1, Pula e muda" - // If T is one, skip the next instruction - // and toggle T. - if ((FLAGS & T) == 1){ - INCREMENT_PC_4K; //skip - FLAGS &= ~T; //set T=0 - } - return; - case 0x94: - //SV 0 = "Se V=0, Pula" - // If V is zero, skip the next instruction - if ((FLAGS & V) == 0) - INCREMENT_PC_4K; //skip - return; - case 0x95: - //SVM 0 = "Se V=0, Pula e muda" - // If V is zero, skip the next instruction - // and toggle V. - if ((FLAGS & V) == 0){ - INCREMENT_PC_4K; //skip - FLAGS |= V; //set V=1 - } - return; - case 0x96: - //SV 1 = "Se V=1, Pula" - // If V is one, skip the next instruction - if ((FLAGS & V) == 1) - INCREMENT_PC_4K; //skip - return; - case 0x97: - //SVM 1 = "Se V=1, Pula e muda" - // If V is one, skip the next instruction - // and toggle V. - if ((FLAGS & V) == 1){ - INCREMENT_PC_4K; //skip - FLAGS &= ~V; //set V=0 - } - return; - case 0x98: - //PUL="Pula para /002 a limpa estado de interrupção" - // Jump to address /002 and disables interrupts - PC = 0x002; - m_interrupts_enabled = false; - return; - case 0x99: - //TRE="Troca conteúdos de ACC e EXT" - // Exchange the value of the accumulator with the ACC extension register - value = ACC; - ACC = READ_ACC_EXTENSION_REG(); - WRITE_ACC_EXTENSION_REG(value); - return; case 0x9A: //INIB="Inibe" // disables interrupts @@ -527,7 +377,7 @@ void patinho_feio_cpu_device::execute_instruction() ACC = (ACC & (1 << 7)) | ACC >> 1; break; default: - printf("Illegal instruction: %02X %02X\n", m_opcode, value); + printf("Illegal instruction: %02X %02X\n", opcode, value); return; } } @@ -535,194 +385,105 @@ void patinho_feio_cpu_device::execute_instruction() return; } - switch (m_opcode & 0xF0){ + switch (opcode & 0xF0){ case 0x00: //PLA = "Pula": Jump to address - compute_effective_address((m_opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); INCREMENT_PC_4K; - PC = m_addr; + PC = addr; return; case 0x10: //PLAX = "Pula indexado": Jump to indexed address - tmp = (m_opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); + tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); INCREMENT_PC_4K; m_idx = READ_INDEX_REG(); - compute_effective_address(m_idx + tmp); - PC = m_addr; + PC = compute_effective_address(m_idx + tmp); return; case 0x20: //ARM = "Armazena": Store the value of the accumulator into a given memory position - compute_effective_address((m_opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); INCREMENT_PC_4K; - WRITE_BYTE_PATINHO(m_addr, ACC); + WRITE_BYTE_PATINHO(addr, ACC); return; case 0x30: //ARMX = "Armazena indexado": Store the value of the accumulator into a given indexed memory position - tmp = (m_opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); + tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); INCREMENT_PC_4K; m_idx = READ_INDEX_REG(); - compute_effective_address(m_idx + tmp); - WRITE_BYTE_PATINHO(m_addr, ACC); + addr = compute_effective_address(m_idx + tmp); + WRITE_BYTE_PATINHO(addr, ACC); return; case 0x40: //CAR = "Carrega": Load a value from a given memory position into the accumulator - compute_effective_address((m_opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); INCREMENT_PC_4K; - ACC = READ_BYTE_PATINHO(m_addr); + ACC = READ_BYTE_PATINHO(addr); return; case 0x50: //CARX = "Carga indexada": Load a value from a given indexed memory position into the accumulator - tmp = (m_opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); + tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); INCREMENT_PC_4K; m_idx = READ_INDEX_REG(); - compute_effective_address(m_idx + tmp); - ACC = READ_BYTE_PATINHO(m_addr); + addr = compute_effective_address(m_idx + tmp); + ACC = READ_BYTE_PATINHO(addr); return; case 0x60: //SOM = "Soma": Add a value from a given memory position into the accumulator - compute_effective_address((m_opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); INCREMENT_PC_4K; - ACC += READ_BYTE_PATINHO(m_addr); + ACC += READ_BYTE_PATINHO(addr); //TODO: update V and T flags return; case 0x70: //SOMX = "Soma indexada": Add a value from a given indexed memory position into the accumulator - tmp = (m_opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); + tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); INCREMENT_PC_4K; m_idx = READ_INDEX_REG(); - compute_effective_address(m_idx + tmp); - ACC += READ_BYTE_PATINHO(m_addr); + addr = compute_effective_address(m_idx + tmp); + ACC += READ_BYTE_PATINHO(addr); //TODO: update V and T flags return; case 0xA0: //PLAN = "Pula se ACC negativo": Jump to a given address if ACC is negative - compute_effective_address((m_opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); INCREMENT_PC_4K; if ((signed char) ACC < 0) - PC = m_addr; + PC = addr; return; case 0xB0: //PLAZ = "Pula se ACC for zero": Jump to a given address if ACC is zero - compute_effective_address((m_opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); INCREMENT_PC_4K; if (ACC == 0) - PC = m_addr; + PC = addr; return; case 0xC0: //Executes I/O functions //TODO: Implement-me! value = READ_BYTE_PATINHO(PC); INCREMENT_PC_4K; - channel = m_opcode & 0x0F; + channel = opcode & 0x0F; function = value & 0x0F; switch(value & 0xF0){ case 0x10: - switch(function) - { - case 0: - // FNC /n0: Desliga flip-flop PERMITE/IMPEDE para - // o dispositivo n (isto é, impede inter- - // -rupcao do dispositivo n). - // - // Turns off the interrupt ENABLE/DISABLE - // flip-flop for channel n. - //TODO: Implement-me! - break; - case 1: - // FNC /n1: Desliga flip-flop de ESTADO do dispo- - // -sitivo n ( ESTADO = "busy" ). - // - // Turns off STATUS flip-flop for - // channel n ( STATUS = "busy" ). - m_iodev_status[channel] = IODEV_BUSY; - break; - case 2: - // FNC /n2: Liga flip-flop de ESTADO do dispo- - // -sitivo n ( ESTADO = "ready" ). - // - // Turns on STATUS flip-flop for - // channel n ( STATUS = "ready" ). - m_iodev_status[channel] = IODEV_READY; - break; - case 4: - // FNC /n4: Desliga flip-flop de PEDIDO de inter- - // rupcao do dispositivo n. - // - // Turns off the interrupt REQUEST - // flip-flop for channel n. - //TODO: Implement-me! - break; - case 5: - // FNC /n5: Liga flip-flop PERMITE/IMPEDE para o - // dispositivo n (isto é, permite inter- - // -rupcao do dispositivo n). - // - // Turns on the interrupt ENABLE/DISABLE - // flip-flop for channel n. - //TODO: Implement-me! - break; - case 6: - // FNC /n6: Liga flip-flop de CONTROLE e desliga - // flip-flop de ESTADO (ESTADO = "BUSY") - // do dispositivo n . - // - // Turns on the CONTROL flip-flop and - // turns off the STATUS flip-flop for - // channel n ( STATUS = "BUSY"). - m_iodev_control[channel] = REQUEST; - m_iodev_status[channel] = IODEV_BUSY; - break; - case 7: - // FNC /n7: Desliga flip-flop de CONTROLE do dis- - // positivo n. - // - // Turns off the CONTROL flip-flop for - // for channel n. - m_iodev_control[channel] = NO_REQUEST; - break; - case 8: - // FNC /n8: Só funciona na leitora de fita, ca- - // nal /E. Ignora todos os "feed-fra- - // -mes" ("bytes" nulos) da fita, ate' a - // proxima perfuracao (1o "byte" nao - // nulo). - // - // Only works with the punched tape reader, - // device on channel /E. Ignores all - // "feed-frames" (null 'bytes') of the tape, - // until the first punch (1st non-zero 'byte'). - if (channel==0xE){ - //TODO: Implement-me! - } else { - printf("Function 8 of the /FNC instruction can only be used with"\ - "the papertape reader device at channel /E.\n"); - } - break; - default: - printf("Invalid function (#%d) specified in /FNC instruction.\n", function); - } + printf("Unimplemented FNC /%X%X instruction\n", channel, function); break; case 0x20: //SAL="Salta" // Skips a couple bytes if a condition is met - skip = false; + skip = false; switch(function) { case 1: - skip = (m_iodev_status[channel] == IODEV_READY); + if (m_peripherals[channel].io_status == DEVICE_READY) + skip = true; break; case 2: - /* TODO: - skip = false; - if (! m_iodev_is_ok_cb[channel].isnull() - && m_iodev_is_ok_cb[channel](0)) */ + if (m_peripherals[channel].device_is_ok) skip = true; break; case 4: - /*TODO: - skip =false; - if (! m_iodev_IRQ_cb[channel].isnull() - && m_iodev_IRQ_cb[channel](0) == true)*/ + if (m_peripherals[channel].IRQ_request == true) skip = true; break; } @@ -733,28 +494,21 @@ void patinho_feio_cpu_device::execute_instruction() } break; case 0x40: - /* ENTR = "Input data from I/O device" */ - ACC = m_iodev_incoming_byte[channel]; - m_iodev_control[channel] = NO_REQUEST; //TODO: <-- check if this is correct + printf("Unimplemented ENTR /%X0 instruction\n", channel); break; case 0x80: - /* SAI = "Output data to I/O device" */ - if (m_iodev_write_cb[channel].isnull()){ - printf("Warning: There's no device hooked up at I/O address 0x%X", channel); - } else { - m_iodev_write_cb[channel](ACC); - } + printf("Unimplemented SAI /%X0 instruction (ACC = 0x%02X '%c')\n", channel, ACC, ACC); break; } return; case 0xE0: //SUS = "Subtrai um ou Salta": Subtract one from the data in the given address // or, if the data is zero, then simply skip a couple bytes. - compute_effective_address((m_opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); INCREMENT_PC_4K; - value = READ_BYTE_PATINHO(m_addr); + value = READ_BYTE_PATINHO(addr); if (value > 0){ - WRITE_BYTE_PATINHO(m_addr, value-1); + WRITE_BYTE_PATINHO(addr, value-1); } else { INCREMENT_PC_4K; INCREMENT_PC_4K; @@ -764,14 +518,14 @@ void patinho_feio_cpu_device::execute_instruction() //PUG = "Pula e guarda": Jump and store. // It stores the return address to addr and addr+1 // And then jumps to addr+2 - compute_effective_address((m_opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); INCREMENT_PC_4K; - WRITE_BYTE_PATINHO(m_addr, (PC >> 8) & 0x0F); - WRITE_BYTE_PATINHO(m_addr+1, PC & 0xFF); - PC = m_addr+2; + WRITE_BYTE_PATINHO(addr, (PC >> 8) & 0x0F); + WRITE_BYTE_PATINHO(addr+1, PC & 0xFF); + PC = addr+2; return; } - printf("unimplemented opcode: 0x%02X\n", m_opcode); + printf("unimplemented opcode: 0x%02X\n", opcode); } offs_t patinho_feio_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) diff --git a/src/devices/cpu/patinhofeio/patinho_feio.h b/src/devices/cpu/patinhofeio/patinho_feio.h new file mode 100644 index 00000000000..7057d318c30 --- /dev/null +++ b/src/devices/cpu/patinhofeio/patinho_feio.h @@ -0,0 +1,107 @@ +// license:GPL-2.0+ +// copyright-holders:Felipe Sanches +#pragma once + +#ifndef __PATINHOFEIO_H__ +#define __PATINHOFEIO_H__ + +#define MCFG_PATINHO_RC_READ_CB(_devcb) \ + devcb = &patinho_feio_cpu_device::set_rc_read_callback(*device, DEVCB_##_devcb); + +/* register IDs */ +enum +{ + PATINHO_FEIO_CI=1, PATINHO_FEIO_ACC, PATINHO_FEIO_IDX, PATINHO_FEIO_RC +}; + +enum { + DEVICE_BUSY=0, + DEVICE_READY=1 +}; + +class patinho_feio_peripheral +{ +public: + patinho_feio_peripheral() + : io_status(DEVICE_READY) + , device_is_ok(true) + , IRQ_request(false) + { }; + + int io_status; + bool device_is_ok; + bool IRQ_request; +}; + +class patinho_feio_cpu_device : public cpu_device +{ +public: + // construction/destruction + patinho_feio_cpu_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock); + + template static devcb_base &set_rc_read_callback(device_t &device, _Object object) { return downcast(device).m_rc_read_cb.set_callback(object); } + +protected: + + virtual void execute_run() override; + virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) override; + + address_space_config m_program_config; + + /* processor registers */ + unsigned char m_acc; /* accumulator (8 bits) */ + unsigned int m_pc; /* program counter (12 bits) + * Actual register name is CI, which + * stands for "Contador de Instrucao" + * or "instructions counter". + */ + unsigned int m_rc; /* RC = "Registrador de Chaves" (Keys Register) + * It represents the 12 bits of input data + * from toggle switches in the computer panel + */ + unsigned char m_idx; + + /* processor state flip-flops */ + bool m_run; /* processor is running */ + bool m_wait_for_interrupt; + bool m_interrupts_enabled; + bool m_scheduled_IND_bit_reset; + bool m_indirect_addressing; + + int m_flags; + // V = "Vai um" (Carry flag) + // T = "Transbordo" (Overflow flag) + + patinho_feio_peripheral m_peripherals[16]; + + int m_address_mask; /* address mask */ + int m_icount; + + address_space *m_program; + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_execute_interface overrides + virtual UINT32 execute_min_cycles() const override { return 1; } + virtual UINT32 execute_max_cycles() const override { return 2; } + + // device_memory_interface overrides + virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override { return (spacenum == AS_PROGRAM) ? &m_program_config : nullptr; } + + // device_disasm_interface overrides + virtual UINT32 disasm_min_opcode_bytes() const override { return 1; } + virtual UINT32 disasm_max_opcode_bytes() const override { return 2; } + +private: + void execute_instruction(); + unsigned int compute_effective_address(unsigned int addr); + UINT16 read_panel_keys_register(); + devcb_read16 m_rc_read_cb; +}; + + +extern const device_type PATINHO_FEIO; + +#endif /* __PATINHOFEIO_H__ */ diff --git a/src/devices/cpu/patinhofeio/patinho_feio_dasm.cpp b/src/devices/cpu/patinhofeio/patinho_feio_dasm.cpp index 9365a1c0c76..f2f2899af6e 100644 --- a/src/devices/cpu/patinhofeio/patinho_feio_dasm.cpp +++ b/src/devices/cpu/patinhofeio/patinho_feio_dasm.cpp @@ -1,13 +1,14 @@ // license:GPL-2.0+ // copyright-holders:Felipe Sanches #include "emu.h" -#include "cpu/patinhofeio/patinhofeio_cpu.h" +#include "cpu/patinhofeio/patinho_feio.h" CPU_DISASSEMBLE( patinho_feio ) { int addr, value, n, f; - switch (oprom[0] & 0xF0) { + switch (oprom[0] & 0xF0) + { case 0x00: //PLA = "Pula": Unconditionally JUMP to effective address addr = (oprom[0] & 0x0F) << 8 | oprom[1]; @@ -123,7 +124,8 @@ CPU_DISASSEMBLE( patinho_feio ) return 2; } - switch (oprom[0]) { + switch (oprom[0]) + { case 0x80: sprintf (buffer, "LIMPO"); return 1; case 0x81: sprintf (buffer, "UM"); return 1; case 0x82: sprintf (buffer, "CMP1"); return 1; diff --git a/src/mame/drivers/patinho_feio.cpp b/src/mame/drivers/patinho_feio.cpp index 65a1e5309ec..e40274c884a 100644 --- a/src/mame/drivers/patinho_feio.cpp +++ b/src/mame/drivers/patinho_feio.cpp @@ -5,157 +5,37 @@ */ #include "emu.h" -#include "bus/generic/slot.h" -#include "bus/generic/carts.h" -#include "softlist.h" -#include "cpu/patinhofeio/patinhofeio_cpu.h" -#include "includes/patinhofeio.h" -#include "patinho.lh" +#include "cpu/patinhofeio/patinho_feio.h" + +class patinho_feio_state : public driver_device +{ +public: + patinho_feio_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + //,m_maincpu(*this, "maincpu") + { } + + DECLARE_DRIVER_INIT(patinho_feio); + DECLARE_READ16_MEMBER(rc_r); + void load_tape(const char* name); + void load_raw_data(const char* name, unsigned int start_address, unsigned int data_length); + virtual void machine_start() override; +// virtual void machine_reset(); +// required_device m_maincpu; +}; /* driver init function */ DRIVER_INIT_MEMBER(patinho_feio_state, patinho_feio) { - m_out = &output(); - m_prev_ACC = 0; - m_prev_opcode = 0; - m_prev_mem_data = 0; - m_prev_mem_addr = 0; - m_prev_PC = 0; - m_prev_FLAGS = 0; - m_prev_RC = 0; } READ16_MEMBER(patinho_feio_state::rc_r) { - return ioport("RC")->read(); + return ioport("RC_HIGH")->read() << 8 | ioport("RC_LOW")->read(); } -READ16_MEMBER(patinho_feio_state::buttons_r) -{ - return ioport("BUTTONS")->read(); -} - -void patinho_feio_state::update_panel(UINT8 ACC, UINT8 opcode, UINT8 mem_data, UINT16 mem_addr, UINT16 PC, UINT8 FLAGS, UINT16 RC, UINT8 mode){ - char lamp_id[11]; - const char* button_names[] = { - "NORMAL", - "CICLOUNICO", - "INSTRUCAOUNICA", - "ENDERECAMENTO", - "ARMAZENAMENTO", - "EXPOSICAO" - }; - - for (int i=0; i<6; i++){ - m_out->set_value(button_names[i], (mode == i) ? 1 : 0); - } - - for (int i=0; i<8; i++){ - if ((m_prev_ACC ^ ACC) & (1 << i)){ - sprintf(lamp_id, "acc%d", i); - m_out->set_value(lamp_id, (ACC >> i) & 1); - } - if ((m_prev_opcode ^ opcode) & (1 << i)){ - sprintf(lamp_id, "opcode%d", i); - m_out->set_value(lamp_id, (opcode >> i) & 1); - } - if ((m_prev_mem_data ^ mem_data) & (1 << i)){ - sprintf(lamp_id, "mem_data%d", i); - m_out->set_value(lamp_id, (mem_data >> i) & 1); - } - } - m_prev_ACC = ACC; - m_prev_opcode = opcode; - m_prev_mem_data = mem_data; - - for (int i=0; i<12; i++){ - if ((m_prev_mem_addr ^ mem_addr) & (1 << i)){ - sprintf(lamp_id, "mem_addr%d", i); - m_out->set_value(lamp_id, (mem_addr >> i) & 1); - } - if ((m_prev_PC ^ PC) & (1 << i)){ - sprintf(lamp_id, "pc%d", i); - m_out->set_value(lamp_id, (PC >> i) & 1); - } - if ((m_prev_RC ^ RC) & (1 << i)){ - sprintf(lamp_id, "rc%d", i); - m_out->set_value(lamp_id, (RC >> i) & 1); - } - } - m_prev_mem_addr = mem_addr; - m_prev_PC = PC; - m_prev_RC = RC; - - if ((m_prev_FLAGS ^ FLAGS) & (1 << 0)) m_out->set_value("flags0", (FLAGS >> 0) & 1); - if ((m_prev_FLAGS ^ FLAGS) & (1 << 1)) m_out->set_value("flags1", (FLAGS >> 1) & 1); - m_prev_FLAGS = FLAGS; -} - -WRITE8_MEMBER(patinho_feio_state::decwriter_data_w) -{ - m_decwriter->write(space, 0, data); - - m_maincpu->set_iodev_status(0xA, IODEV_BUSY); - - if (data == 0x0D){ - m_decwriter_timer->adjust(attotime::from_hz(1/0.700)); //carriage return takes 700 msecs - } else { - m_decwriter_timer->adjust(attotime::from_hz(10)); //10 characters per second - } - m_decwriter_timer->enable(1); //start the timer -} - -/* - timer callback to generate decwriter char print completion signal -*/ -TIMER_CALLBACK_MEMBER(patinho_feio_state::decwriter_callback) -{ - m_maincpu->set_iodev_status(0xA, IODEV_READY); - m_decwriter_timer->enable(0); //stop the timer -} - -WRITE8_MEMBER(patinho_feio_state::decwriter_kbd_input) -{ - m_maincpu->transfer_byte_from_external_device(0xA, ~data); -} - -WRITE8_MEMBER(patinho_feio_state::teletype_data_w) -{ - m_tty->write(space, 0, data); - - m_maincpu->set_iodev_status(0xB, IODEV_READY); - m_teletype_timer->adjust(attotime::from_hz(10)); //10 characters per second - m_teletype_timer->enable(1); //start the timer -} - -/* - timer callback to generate teletype char print completion signal -*/ -TIMER_CALLBACK_MEMBER(patinho_feio_state::teletype_callback) -{ - m_maincpu->set_iodev_status(0xB, IODEV_READY); - m_teletype_timer->enable(0); //stop the timer -} - -WRITE8_MEMBER(patinho_feio_state::teletype_kbd_input) -{ - //I figured out that the data is provided inverted (2's complement) - //based on a comment in the source code listing of the HEXAM program. - //It is not clear though, if all I/O devices complement the data when - //communicating with the computer, or if this behavious is a particular - //caracteristics of the teletype. - - m_maincpu->transfer_byte_from_external_device(0xB, ~data); -} - -/* The hardware does not perform this checking. - This is implemented here only for debugging purposes. - - Also, proper punched paper tape emulation does - not use this function at all. -*/ void patinho_feio_state::load_tape(const char* name){ UINT8 *RAM = (UINT8 *) memshare("maincpu:internalram")->ptr(); UINT8 *data = memregion(name)->base(); @@ -170,7 +50,7 @@ void patinho_feio_state::load_tape(const char* name){ if (checksum != expected_checksum){ printf("[WARNING] Tape \"%s\": checksum = 0x%02X (expected 0x%02X)\n", - name, (unsigned char) checksum, (unsigned char) expected_checksum); + name, (unsigned char) checksum, (unsigned char) expected_checksum); } memcpy(&RAM[start_address], &data[3], data_length); @@ -183,21 +63,7 @@ void patinho_feio_state::load_raw_data(const char* name, unsigned int start_addr memcpy(&RAM[start_address], data, data_length); } -DEVICE_IMAGE_LOAD_MEMBER( patinho_feio_state, patinho_tape ) -{ - if (image.software_entry() != nullptr){ - paper_tape_length = image.get_software_region_length("rom"); - paper_tape_data = image.get_software_region("rom"); - paper_tape_address = 0; - } - - return IMAGE_INIT_PASS; -} - void patinho_feio_state::machine_start(){ - m_teletype_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(patinho_feio_state::teletype_callback),this)); - m_decwriter_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(patinho_feio_state::decwriter_callback),this)); - // Copy some programs directly into RAM. // This is a hack for setting up the computer // while we don't support loading programs @@ -211,43 +77,24 @@ void patinho_feio_state::machine_start(){ // Allows users to load programs from the // console into the computer memory. load_raw_data("hexam", 0xE00, 0x0D5); - - load_raw_data("loader", 0xF80, 0x080); - //load_raw_data("micro_pre_loader", 0x000, 0x02A); //this is still experimental } static INPUT_PORTS_START( patinho_feio ) - PORT_START("RC") - PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 0") PORT_CODE(KEYCODE_EQUALS) PORT_TOGGLE - PORT_BIT(0x002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 1") PORT_CODE(KEYCODE_MINUS) PORT_TOGGLE - PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 2") PORT_CODE(KEYCODE_0) PORT_TOGGLE - PORT_BIT(0x008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 3") PORT_CODE(KEYCODE_9) PORT_TOGGLE - PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 4") PORT_CODE(KEYCODE_8) PORT_TOGGLE - PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 5") PORT_CODE(KEYCODE_7) PORT_TOGGLE - PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 6") PORT_CODE(KEYCODE_6) PORT_TOGGLE - PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 7") PORT_CODE(KEYCODE_5) PORT_TOGGLE - PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 8") PORT_CODE(KEYCODE_4) PORT_TOGGLE - PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 7") PORT_CODE(KEYCODE_3) PORT_TOGGLE - PORT_BIT(0x400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 10") PORT_CODE(KEYCODE_2) PORT_TOGGLE - PORT_BIT(0x800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 11") PORT_CODE(KEYCODE_1) PORT_TOGGLE + PORT_START("RC_LOW") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 0") PORT_CODE(KEYCODE_EQUALS) PORT_TOGGLE + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 1") PORT_CODE(KEYCODE_MINUS) PORT_TOGGLE + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 2") PORT_CODE(KEYCODE_0) PORT_TOGGLE + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 3") PORT_CODE(KEYCODE_9) PORT_TOGGLE + PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 4") PORT_CODE(KEYCODE_8) PORT_TOGGLE + PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 5") PORT_CODE(KEYCODE_7) PORT_TOGGLE + PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 6") PORT_CODE(KEYCODE_6) PORT_TOGGLE + PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 7") PORT_CODE(KEYCODE_5) PORT_TOGGLE - PORT_START("BUTTONS") - /* Modo de Operação: EXECUÇÃO */ - PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("NORMAL") PORT_CODE(KEYCODE_A) - PORT_BIT(0x002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("CICLO ÚNICO") PORT_CODE(KEYCODE_S) - PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("INSTRUÇÃO ÚNICA") PORT_CODE(KEYCODE_D) - /* Modo de Operação: MEMÓRIA */ - PORT_BIT(0x008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ENDEREÇAMENTO") PORT_CODE(KEYCODE_Z) - PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ARMAZENAMENTO") PORT_CODE(KEYCODE_X) - PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("EXPOSIÇÃO") PORT_CODE(KEYCODE_C) - /* Comando: */ - PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ESPERA") PORT_CODE(KEYCODE_Q) - PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("INTERRUPÇÃO") PORT_CODE(KEYCODE_W) - PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PARTIDA") PORT_CODE(KEYCODE_E) - PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PREPARAÇÃO") PORT_CODE(KEYCODE_R) - /* Switches */ - PORT_BIT(0x400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ENDEREÇAMENTO (Fixo/Sequencial)") PORT_CODE(KEYCODE_N) PORT_TOGGLE - PORT_BIT(0x800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("MEMÓRIA (Liberada/Protegida)") PORT_CODE(KEYCODE_M) PORT_TOGGLE + PORT_START("RC_HIGH") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 8") PORT_CODE(KEYCODE_4) PORT_TOGGLE + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 7") PORT_CODE(KEYCODE_3) PORT_TOGGLE + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 10") PORT_CODE(KEYCODE_2) PORT_TOGGLE + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RC bit 11") PORT_CODE(KEYCODE_1) PORT_TOGGLE INPUT_PORTS_END static MACHINE_CONFIG_START( patinho_feio, patinho_feio_state ) @@ -255,66 +102,14 @@ static MACHINE_CONFIG_START( patinho_feio, patinho_feio_state ) /* CPU @ approx. 500 kHz (memory cycle time is 2usec) */ MCFG_CPU_ADD("maincpu", PATINHO_FEIO, 500000) MCFG_PATINHO_RC_READ_CB(READ16(patinho_feio_state, rc_r)) - MCFG_PATINHO_BUTTONS_READ_CB(READ16(patinho_feio_state, buttons_r)) - - /* Printer */ -// MCFG_PATINHO_IODEV_WRITE_CB(0x5, WRITE8(patinho_feio_state, printer_data_w)) - - /* Papertape Puncher */ -// MCFG_PATINHO_IODEV_WRITE_CB(0x8, WRITE8(patinho_feio_state, papertape_punch_data_w)) - - /* Card Reader */ -// MCFG_PATINHO_IODEV_READ_CB(0x9, READ8(patinho_feio_state, cardreader_data_r)) - - /* DECWRITER - (max. speed: ?) */ - MCFG_PATINHO_IODEV_WRITE_CB(0xA, WRITE8(patinho_feio_state, decwriter_data_w)) - - /* Teleprinter - TeleType ASR33 - (max. speed: 10 characteres per second) - with paper tape reading (and optionally punching) capabilities */ - MCFG_PATINHO_IODEV_WRITE_CB(0xB, WRITE8(patinho_feio_state, teletype_data_w)) - - /* Papertape Reader - Hewlett-Packard HP-2737-A - Optical Papertape Reader (max. speed: 300 characteres per second) */ -// MCFG_PATINHO_IODEV_READ_CB(0xE, READ8(patinho_feio_state, papertapereader_data_r)) - - /* DECWRITER */ - MCFG_DEVICE_ADD("decwriter", TELEPRINTER, 0) - MCFG_GENERIC_TELEPRINTER_KEYBOARD_CB(WRITE8(patinho_feio_state, decwriter_kbd_input)) - - /* Teletype */ - MCFG_DEVICE_ADD("teletype", TELEPRINTER, 1) - MCFG_GENERIC_TELEPRINTER_KEYBOARD_CB(WRITE8(patinho_feio_state, teletype_kbd_input)) - - /* punched tape */ - MCFG_GENERIC_CARTSLOT_ADD("cartslot", generic_plain_slot, "patinho_tape") - MCFG_GENERIC_EXTENSIONS("bin") - MCFG_GENERIC_LOAD(patinho_feio_state, patinho_tape) - - MCFG_DEFAULT_LAYOUT(layout_patinho) - - // software lists -// MCFG_SOFTWARE_LIST_ADD("tape_list", "patinho") MACHINE_CONFIG_END ROM_START( patinho ) ROM_REGION( 0x0d5, "hexam", 0 ) - ROM_LOAD( "apendice_g__hexam.bin", 0x000, 0x0d5, CRC(e608f6d3) SHA1(3f76b5f91d9b2573e70919539d47752e7623e40a) ) + ROM_LOAD( "apendice_g__hexam.bin", 0x000, 0x0d5, CRC(c6addc59) SHA1(126bc97247eac45c58708eaac216c2438e9e4af9) ) ROM_REGION( 0x0d5, "exemplo_16.7", 0 ) ROM_LOAD( "exemplo_16.7.bin", 0x000, 0x028, CRC(0a87ac8d) SHA1(7c35ac3eed9ed239f2ef56c26e6f0c59f635e1ac) ) - - ROM_REGION( 0x080, "loader", 0 ) - ROM_LOAD( "loader.bin", 0x000, 0x080, BAD_DUMP CRC(c2a8fa9d) SHA1(0ae4f711ef5d6e9d26c611fd2c8c8ac45ecbf9e7) ) - - /* Micro pre-loader: - This was re-created by professor Joao Jose Neto based on his vague - recollection of sequences of opcode values from almost 40 years ago :-) */ - ROM_REGION( 0x02a, "micro_pre_loader", 0 ) - ROM_LOAD( "micro-pre-loader.bin", 0x000, 0x02a, CRC(1921feab) SHA1(bb063102e44e9ab963f95b45710141dc2c5046b0) ) ROM_END /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */