diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index dc2eb538b00..985d47c0611 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -1435,6 +1435,22 @@ if (CPUS["PDP1"]~=null or _OPTIONS["with-tools"]) then table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/pdp1/tx0dasm.cpp") end +-------------------------------------------------- +-- PATINHO FEIO - Escola Politecnica - USP (Brazil) +--@src/devices/cpu/patinhofeio/patinho_feio.h,CPUS["PATINHOFEIO"] = true +-------------------------------------------------- + +if (CPUS["PATINHOFEIO"]~=null) then + files { + MAME_DIR .. "src/devices/cpu/patinhofeio/patinho_feio.cpp", + MAME_DIR .. "src/devices/cpu/patinhofeio/patinho_feio.h", + } +end + +if (CPUS["PATINHOFEIO"]~=null or _OPTIONS["with-tools"]) then + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/patinhofeio/patinho_feio_dasm.cpp") +end + -------------------------------------------------- -- Motorola PowerPC series --@src/devices/cpu/powerpc/ppc.h,CPUS["POWERPC"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index e5436770e03..5b16be78d7e 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -91,6 +91,7 @@ CPUS["APEXC"] = true CPUS["CP1610"] = true CPUS["F8"] = true CPUS["LH5801"] = true +CPUS["PATINHOFEIO"] = true CPUS["PDP1"] = true CPUS["SATURN"] = true CPUS["SC61860"] = true @@ -852,6 +853,7 @@ function linkProjects_mame_mess(_target, _subtarget) "ultratec", "unisonic", "unisys", + "usp", "veb", "vidbrain", "videoton", @@ -2845,6 +2847,11 @@ files { MAME_DIR .. "src/mame/drivers/univac.cpp", } +createMESSProjects(_target, _subtarget, "usp") +files { + MAME_DIR .. "src/mame/drivers/patinho_feio.cpp", +} + createMESSProjects(_target, _subtarget, "veb") files { MAME_DIR .. "src/mame/drivers/chessmst.cpp", diff --git a/src/devices/cpu/patinhofeio/patinho_feio.cpp b/src/devices/cpu/patinhofeio/patinho_feio.cpp new file mode 100644 index 00000000000..9377ad259f8 --- /dev/null +++ b/src/devices/cpu/patinhofeio/patinho_feio.cpp @@ -0,0 +1,536 @@ +// license:GPL-2.0+ +// copyright-holders:Felipe Sanches +/* + CPU emulation for Patinho Feio, the first computer designed and manufactured in Brazil +*/ + +#include "emu.h" +#include "debugger.h" +#include "patinho_feio.h" + +#define PC m_pc //The program counter is called "contador de instrucoes" in portuguese +#define ACC m_acc +#define RC read_panel_keys_register() +#define FLAGS m_flags + +#define V 0x01 // V = "Vai um" (Carry) +#define T 0x02 // T = "Transbordo" (Overflow) + +#define READ_BYTE_PATINHO(A) (m_program->read_byte(A)) +#define WRITE_BYTE_PATINHO(A,V) (m_program->write_byte(A,V)) + +#define READ_WORD_PATINHO(A) (READ_BYTE_PATINHO(A+1)*256 + READ_BYTE_PATINHO(A)) + +#define READ_INDEX_REG() READ_BYTE_PATINHO(0x000) +#define WRITE_INDEX_REG(V) { WRITE_BYTE_PATINHO(0x000, V); m_idx = V; } + +#define ADDRESS_MASK_4K 0xFFF +#define INCREMENT_PC_4K (PC = (PC+1) & ADDRESS_MASK_4K) + +unsigned int patinho_feio_cpu_device::compute_effective_address(unsigned int addr){ + unsigned int retval = addr; + if (m_indirect_addressing){ + 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") +ADDRESS_MAP_END + +patinho_feio_cpu_device::patinho_feio_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : 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) +{ +} + +UINT16 patinho_feio_cpu_device::read_panel_keys_register(){ + if (!m_rc_read_cb.isnull()) + m_rc = m_rc_read_cb(0); + else + m_rc = 0; + + return m_rc; +} + +void patinho_feio_cpu_device::device_start() +{ + m_program = &space(AS_PROGRAM); + + save_item(NAME(m_pc)); + save_item(NAME(m_acc)); + save_item(NAME(m_rc)); + save_item(NAME(m_idx)); + save_item(NAME(m_flags)); + + // 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_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"); + + if (m_rc_read_cb.isnull()){ + fatalerror("Panel keys register not found!"); + } else { + m_rc_read_cb.resolve(); + } + + m_icountptr = &m_icount; +} + +void patinho_feio_cpu_device::device_reset() +{ + m_pc = 0x006; + m_acc = 0; + m_rc = 0; + m_idx = READ_INDEX_REG(); + m_flags = 0; + m_run = true; + m_scheduled_IND_bit_reset = false; + m_indirect_addressing = false; +} + +/* execute instructions on this CPU until icount expires */ +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 --; + } + } + while (m_icount > 0); +} + +/* 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; + unsigned char opcode = READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + + if (m_scheduled_IND_bit_reset) + m_indirect_addressing = false; + + if (m_indirect_addressing) + m_scheduled_IND_bit_reset = true; + + switch (opcode){ + case 0xD2: + //XOR: Computes the bitwise XOR of an immediate into the accumulator + ACC ^= READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + //TODO: update T and V flags + return; + case 0xD4: + //NAND: Computes the bitwise XOR of an immediate into the accumulator + ACC = ~(ACC & READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + //TODO: update T and V flags + return; + case 0xD8: + //SOMI="Soma Imediato": + // Add an immediate into the accumulator + ACC += READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + //TODO: update T and V flags + return; + case 0xDA: + //CARI="Carrega Imediato": + // Load an immediate into the accumulator + ACC = READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + return; + case 0x80: + //LIMPO: + // Clear accumulator and flags + ACC = 0; + FLAGS = 0; + return; + case 0x81: + //UM="One": + // Load 1 into accumulator + // and clear the flags + ACC = 1; + FLAGS = 0; + return; + case 0x82: + //CMP1: + // Compute One's complement of the accumulator + // and clear the flags + ACC = ~ACC; + FLAGS = 0; + return; + case 0x83: + //CMP2: + // Compute Two's complement of the accumulator + // and updates flags according to the result of the operation + ACC = ~ACC + 1; + FLAGS = 0; //TODO: fix-me (I'm not sure yet how to compute the flags here) + return; + case 0x84: + //LIM="Limpa": + // Clear flags + FLAGS = 0; + return; + case 0x85: + //INC: + // Increment accumulator + ACC++; + FLAGS = 0; //TODO: fix-me (I'm not sure yet how to compute the flags here) + return; + case 0x86: + //UNEG="Um Negativo": + // Load -1 into accumulator and clear flags + ACC = -1; + FLAGS = 0; + return; + case 0x87: + //LIMP1: + // Clear accumulator, reset T and set V + ACC = 0; + FLAGS = V; + return; + case 0x88: + //PNL 0: + ACC = (RC & 0xFF); + FLAGS = 0; + return; + case 0x89: + //PNL 1: + ACC = (RC & 0xFF) + 1; + //TODO: FLAGS = ?; + return; + case 0x8A: + //PNL 2: + ACC = (RC & 0xFF) - ACC - 1; + //TODO: FLAGS = ?; + return; + case 0x8B: + //PNL 3: + ACC = (RC & 0xFF) - ACC; + //TODO: FLAGS = ?; + return; + case 0x8C: + //PNL 4: + ACC = (RC & 0xFF) + ACC; + //TODO: FLAGS = ?; + return; + case 0x8D: + //PNL 5: + ACC = (RC & 0xFF) + ACC + 1; + //TODO: FLAGS = ?; + return; + case 0x8E: + //PNL 6: + ACC = (RC & 0xFF) - 1; + //TODO: FLAGS = ?; + return; + case 0x8F: + //PNL 7: + ACC = (RC & 0xFF); + FLAGS = V; + return; + case 0x9A: + //INIB="Inibe" + // disables interrupts + m_interrupts_enabled = false; + return; + case 0x9B: + //PERM="Permite" + // enables interrupts + m_interrupts_enabled = true; + return; + case 0x9C: + //ESP="Espera": + // Holds execution and waits for an interrupt to occur. + m_run = false; + m_wait_for_interrupt = true; + return; + case 0x9D: + //PARE="Pare": + // Holds execution. This can only be recovered by + // manually triggering execution again by + // pressing the "Partida" (start) button in the panel + m_run = false; + m_wait_for_interrupt = false; + return; + case 0x9E: + //TRI="Troca com Indexador": + // Exchange the value of the accumulator with the index register + value = ACC; + ACC = READ_INDEX_REG(); + WRITE_INDEX_REG(value); + return; + case 0x9F: + //IND="Enderecamento indireto": + // Sets memory addressing for the next instruction to be indirect. + m_indirect_addressing = true; + m_scheduled_IND_bit_reset = false; //the next instruction execution will schedule it. + return; + case 0xD1: + //Bit-Shift/Bit-Rotate instructions + value = READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + for (int i=0; i<4; i++){ + if (value & (1<>= 1; + break; + case 0x20: + //GD="Giro para a Direita" + // Rotate right + FLAGS &= ~V; + if (ACC & 1) + FLAGS |= V; + + ACC = ((ACC & 1) << 7) | (ACC >> 1); + break; + case 0x10: //DDV="Deslocamento para a Direita com Vai-um" + // Shift right with Carry + case 0x30: //GDV="Giro para a Direita com Vai-um" + // Rotate right with Carry + + //both instructions are equivalent + if (FLAGS & V) + tmp = 0x100 | ACC; + else + tmp = ACC; + + FLAGS &= ~V; + if (ACC & 1) + FLAGS |= V; + + ACC = tmp >> 1; + break; + case 0x40: //DE="Deslocamento para a Esquerda" + // Shift left + FLAGS &= ~V; + if (ACC & (1<<7)) + FLAGS |= V; + + ACC <<= 1; + break; + case 0x60: //GE="Giro para a Esquerda" + // Rotate left + FLAGS &= ~V; + if (ACC & (1<<7)) + FLAGS |= V; + + ACC = (ACC << 1) | ((ACC >> 7) & 1); + break; + case 0x50: //DEV="Deslocamento para a Esquerda com Vai-um" + // Shift left with Carry + case 0x70: //GEV="Giro para a Esquerda com Vai-um" + // Rotate left with Carry + + //both instructions are equivalent + if (FLAGS & V) + tmp = (ACC << 1) | 1; + else + tmp = (ACC << 1); + + FLAGS &= ~V; + if (tmp & (1<<8)) + FLAGS |= V; + + ACC = tmp & 0xFF; + break; + case 0x80: //DDS="Deslocamento para a Direita com duplicacao de Sinal" + // Rotate right with signal duplication + FLAGS &= ~V; + if (ACC & 1) + FLAGS |= V; + + ACC = (ACC & (1 << 7)) | ACC >> 1; + break; + default: + printf("Illegal instruction: %02X %02X\n", opcode, value); + return; + } + } + } + return; + } + + switch (opcode & 0xF0){ + case 0x00: + //PLA = "Pula": Jump to address + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + PC = addr; + return; + case 0x10: + //PLAX = "Pula indexado": Jump to indexed address + tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + m_idx = READ_INDEX_REG(); + PC = compute_effective_address(m_idx + tmp); + return; + case 0x20: + //ARM = "Armazena": Store the value of the accumulator into a given memory position + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + WRITE_BYTE_PATINHO(addr, ACC); + return; + case 0x30: + //ARMX = "Armazena indexado": Store the value of the accumulator into a given indexed memory position + tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + m_idx = READ_INDEX_REG(); + 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 + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + ACC = READ_BYTE_PATINHO(addr); + return; + case 0x50: + //CARX = "Carga indexada": Load a value from a given indexed memory position into the accumulator + tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + m_idx = READ_INDEX_REG(); + 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 + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + 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 = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + m_idx = READ_INDEX_REG(); + 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 + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + if ((signed char) ACC < 0) + PC = addr; + return; + case 0xB0: + //PLAZ = "Pula se ACC for zero": Jump to a given address if ACC is zero + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + if (ACC == 0) + PC = addr; + return; + case 0xC0: + //Executes I/O functions + //TODO: Implement-me! + value = READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + channel = opcode & 0x0F; + function = value & 0x0F; + switch(value & 0xF0){ + case 0x10: + 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; + switch(function) + { + case 1: + if (m_peripherals[channel].io_status == DEVICE_READY) + skip = true; + break; + case 2: + if (m_peripherals[channel].device_is_ok) + skip = true; + break; + case 4: + if (m_peripherals[channel].IRQ_request == true) + skip = true; + break; + } + + if (skip){ + INCREMENT_PC_4K; + INCREMENT_PC_4K; + } + break; + case 0x40: + printf("Unimplemented ENTR /%X0 instruction\n", channel); + break; + case 0x80: + 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. + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + value = READ_BYTE_PATINHO(addr); + if (value > 0){ + WRITE_BYTE_PATINHO(addr, value-1); + } else { + INCREMENT_PC_4K; + INCREMENT_PC_4K; + } + return; + case 0xF0: + //PUG = "Pula e guarda": Jump and store. + // It stores the return address to addr and addr+1 + // And then jumps to addr+2 + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + WRITE_BYTE_PATINHO(addr, (PC >> 8) & 0x0F); + WRITE_BYTE_PATINHO(addr+1, PC & 0xFF); + PC = addr+2; + return; + } + 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) +{ + extern CPU_DISASSEMBLE( patinho_feio ); + return CPU_DISASSEMBLE_NAME(patinho_feio)(this, buffer, pc, oprom, opram, 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..b03ce36eccb --- /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(); + virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); + + 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; + + bool 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(); + virtual void device_reset(); + + // device_execute_interface overrides + virtual UINT32 execute_min_cycles() const { return 1; } + virtual UINT32 execute_max_cycles() const { return 2; } + + // device_memory_interface overrides + virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; } + + // device_disasm_interface overrides + virtual UINT32 disasm_min_opcode_bytes() const { return 1; } + virtual UINT32 disasm_max_opcode_bytes() const { 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 new file mode 100644 index 00000000000..ac78ef4be73 --- /dev/null +++ b/src/devices/cpu/patinhofeio/patinho_feio_dasm.cpp @@ -0,0 +1,165 @@ +// license:GPL-2.0+ +// copyright-holders:Felipe Sanches +#include "emu.h" +#include "cpu/patinhofeio/patinho_feio.h" + +CPU_DISASSEMBLE( patinho_feio ) +{ + int addr, value, n, f; + + switch (oprom[0] & 0xF0) + { + case 0x00: + //PLA = "Pula": Unconditionally JUMP to effective address + addr = (oprom[0] & 0x0F) << 8 | oprom[1]; + sprintf (buffer, "PLA /%03X", addr); + return 2; + case 0x10: + //PLAX = "Pulo indexado": Unconditionally JUMP to indexed address + addr = (oprom[0] & 0x0F) << 8 | oprom[1]; + sprintf (buffer, "PLAX (IDX) + /%03X", addr); + return 2; + case 0x20: + //ARM = "Armazena": Stores the contents of the + // accumulator in the given 12bit address + addr = (oprom[0] & 0x0F) << 8 | oprom[1]; + if (addr==0){ + sprintf (buffer, "ARM (IDX)"); + }else{ + sprintf (buffer, "ARM /%03X", addr); + } + return 2; + case 0x30: + //ARMX = "Armazenamento indexado": Stores the contents of the accumulator in the + // given 12bit address (indexed by IDX) + addr = (oprom[0] & 0x0F) << 8 | oprom[1]; + sprintf (buffer, "ARMX (IDX) + /%03X", addr); + return 2; + case 0x40: + //CAR = "Carrega": Loads the contents of the given 12bit address + // into the accumulator + addr = (oprom[0] & 0x0F) << 8 | oprom[1]; + if (addr==0){ + sprintf (buffer, "CAR (IDX)"); + }else{ + sprintf (buffer, "CAR /%03X", addr); + } + return 2; + case 0x50: + //CARX = "Carga indexada": Loads the contents of the given 12bit address + // (indexed by IDX) into the accumulator + addr = (oprom[0] & 0x0F) << 8 | oprom[1]; + sprintf (buffer, "CARX (IDX) + /%03X", addr); + return 2; + case 0x60: + //SOM = "Soma": Adds the contents of the given 12bit address + // into the accumulator + addr = (oprom[0] & 0x0F) << 8 | oprom[1]; + sprintf (buffer, "SOM /%03X", addr); + return 2; + case 0x70: + //SOMX = "Soma indexada": Adds the contents of the given 12bit address + // (indexed by IDX) into the accumulator + addr = (oprom[0] & 0x0F) << 8 | oprom[1]; + sprintf (buffer, "SOMX (IDX) + /%03X", addr); + return 2; + case 0xA0: + //PLAN = "Pula se ACC for negativo": Jumps to the 12bit address + // if the accumulator is negative + addr = (oprom[0] & 0x0F) << 8 | oprom[1]; + sprintf (buffer, "PLAN /%03X", addr); + return 2; + case 0xB0: + //PLAZ = "Pula se ACC for zero": Jumps to the 12bit address + // if the accumulator is zero + addr = (oprom[0] & 0x0F) << 8 | oprom[1]; + sprintf (buffer, "PLAZ /%03X", addr); + return 2; + case 0xC0: + n = (oprom[0] & 0x0F); + f = (oprom[1] & 0x0F); + n+= (n < 10) ? '0' : 'A'-10; + f+= (f < 10) ? '0' : 'A'-10; + switch(oprom[1] & 0xF0) + { + case 0x10: sprintf (buffer, "FNC /%c%c", n, f); return 2; + case 0x20: sprintf (buffer, "SAL /%c%c", n, f); return 2; + case 0x40: sprintf (buffer, "ENTR /%c0", n); return 2; + case 0x80: sprintf (buffer, "SAI /%c0", n); return 2; + } + break; + case 0xD0: + value = oprom[1] & 0x0F; + switch (oprom[0] & 0x0F) + { + case 0x01: + switch (oprom[1] & 0xF0) + { + case 0x00: sprintf (buffer, "DD /%01X", value); return 2; //DD = "Deslocamento para a direita": Shift right + case 0x10: sprintf (buffer, "DDV /%01X", value); return 2; //DDV = "Deslocamento para a direita c/ V": Shift right with carry + case 0x20: sprintf (buffer, "GD /%01X", value); return 2; //GD = "Giro para a direita": Rotate right + case 0x30: sprintf (buffer, "GDV /%01X", value); return 2; //GDV = "Giro para a direita c/ V": Rotate right with carry + case 0x40: sprintf (buffer, "DE /%01X", value); return 2; //DE = "Deslocamento para a esquerda": Shift right + case 0x50: sprintf (buffer, "DEV /%01X", value); return 2; //DEV = "Deslocamento para a esquerda c/ V": Shift right with carry + case 0x60: sprintf (buffer, "GE /%01X", value); return 2; //GE = "Giro para a esquerda": Rotate right + case 0x70: sprintf (buffer, "GEV /%01X", value); return 2; //GEV = "Giro para a esquerda c/ V": Rotate right with carry + case 0x80: sprintf (buffer, "DDS /%01X", value); return 2; //DDS = "Deslocamento para a direita com duplicacao de sinal": Shift right with sign duplication + } + break; + case 0x02: sprintf (buffer, "XOR /%02X", oprom[1]); return 2; //Logical XOR + case 0x04: sprintf (buffer, "NAND /%02X", oprom[1]); return 2; //Logical NAND + case 0x08: sprintf (buffer, "SOMI /%02X", oprom[1]); return 2; //SOMI = "Soma imediata": Add immediate value into accumulator + case 0x0A: sprintf (buffer, "CARI /%02X", oprom[1]); return 2; //CARI = "Carrega imediato": Loads an immediate value into the accumulator + } + break; + case 0xE0: + //SUS = "Subtrai um ou salta" + addr = (oprom[0] & 0x0F) << 8 | oprom[1]; + sprintf (buffer, "SUS /%03X", addr); + return 2; + case 0xF0: + //PUG = "Pula e guarda" + addr = (oprom[0] & 0x0F) << 8 | oprom[1]; + sprintf (buffer, "PUG /%03X", addr); + return 2; + } + + switch (oprom[0]) + { + case 0x80: sprintf (buffer, "LIMPO"); return 1; + case 0x81: sprintf (buffer, "UM"); return 1; + case 0x82: sprintf (buffer, "CMP1"); return 1; + case 0x83: sprintf (buffer, "CMP2"); return 1; + case 0x84: sprintf (buffer, "LIN"); return 1; + case 0x85: sprintf (buffer, "INC"); return 1; + case 0x86: sprintf (buffer, "UNEG"); return 1; + case 0x87: sprintf (buffer, "LIMP1"); return 1; + case 0x88: sprintf (buffer, "PNL 0"); return 1; + case 0x89: sprintf (buffer, "PNL 1"); return 1; + case 0x8A: sprintf (buffer, "PNL 2"); return 1; + case 0x8B: sprintf (buffer, "PNL 3"); return 1; + case 0x8C: sprintf (buffer, "PNL 4"); return 1; + case 0x8D: sprintf (buffer, "PNL 5"); return 1; + case 0x8E: sprintf (buffer, "PNL 6"); return 1; + case 0x8F: sprintf (buffer, "PNL 7"); return 1; + case 0x90: sprintf (buffer, "ST 0"); return 1; + case 0x91: sprintf (buffer, "STM 0"); return 1; + case 0x92: sprintf (buffer, "ST 1"); return 1; + case 0x93: sprintf (buffer, "STM 1"); return 1; + case 0x94: sprintf (buffer, "SV 0"); return 1; + case 0x95: sprintf (buffer, "SVM 0"); return 1; + case 0x96: sprintf (buffer, "SV 1"); return 1; + case 0x97: sprintf (buffer, "SVM 1"); return 1; + case 0x98: sprintf (buffer, "PUL"); return 1; + case 0x99: sprintf (buffer, "TRE"); return 1; + case 0x9A: sprintf (buffer, "INIB"); return 1; + case 0x9B: sprintf (buffer, "PERM"); return 1; + case 0x9C: sprintf (buffer, "ESP"); return 1; + case 0x9D: sprintf (buffer, "PARE"); return 1; + case 0x9E: sprintf (buffer, "TRI"); return 1; + case 0x9F: sprintf (buffer, "IND"); return 1; + } + + sprintf (buffer, "illegal instruction"); + return 1; +} diff --git a/src/mame/drivers/patinho_feio.cpp b/src/mame/drivers/patinho_feio.cpp new file mode 100644 index 00000000000..73643d49797 --- /dev/null +++ b/src/mame/drivers/patinho_feio.cpp @@ -0,0 +1,116 @@ +// license:GPL-2.0+ +// copyright-holders:Felipe Sanches +/* + Patinho Feio +*/ + +#include "emu.h" +#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(); +// virtual void machine_reset(); +// required_device m_maincpu; +}; + +/* + driver init function +*/ +DRIVER_INIT_MEMBER(patinho_feio_state, patinho_feio) +{ +} + +READ16_MEMBER(patinho_feio_state::rc_r) +{ + return ioport("RC_HIGH")->read() << 8 | ioport("RC_LOW")->read(); +} + +void patinho_feio_state::load_tape(const char* name){ + UINT8 *RAM = (UINT8 *) memshare("maincpu:internalram")->ptr(); + UINT8 *data = memregion(name)->base(); + unsigned int data_length = data[0]; + unsigned int start_address = data[1]*256 + data[2]; + INT8 expected_checksum = data[data_length + 3]; + INT8 checksum = 0; + + for (int i = 0; i < data_length + 3; i++){ + checksum -= (INT8) data[i]; + } + + if (checksum != expected_checksum){ + printf("[WARNING] Tape \"%s\": checksum = 0x%02X (expected 0x%02X)\n", + name, (unsigned char) checksum, (unsigned char) expected_checksum); + } + + memcpy(&RAM[start_address], &data[3], data_length); +} + +void patinho_feio_state::load_raw_data(const char* name, unsigned int start_address, unsigned int data_length){ + UINT8 *RAM = (UINT8 *) memshare("maincpu:internalram")->ptr(); + UINT8 *data = memregion(name)->base(); + + memcpy(&RAM[start_address], data, data_length); +} + +void patinho_feio_state::machine_start(){ + // Copy some programs directly into RAM. + // This is a hack for setting up the computer + // while we don't support loading programs + // from punched tape rolls... + + //"absolute program example" from page 16.7 + // Prints "PATINHO FEIO" on the DECWRITER: + load_tape("exemplo_16.7"); + + //"absolute program example" from appendix G: + // Allows users to load programs from the + // console into the computer memory. + load_raw_data("hexam", 0xE00, 0x0D5); +} + +static INPUT_PORTS_START( patinho_feio ) + 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("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 ) + /* basic machine hardware */ + /* 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)) +MACHINE_CONFIG_END + +ROM_START( patinho ) + ROM_REGION( 0x0d5, "hexam", 0 ) + 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_END + +/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */ +COMP( 1972, patinho, 0, 0, patinho_feio, patinho_feio, patinho_feio_state, patinho_feio, "Escola Politécnica - Universidade de São Paulo", "Patinho Feio" , MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING) diff --git a/src/mame/drivers/psikyo.cpp b/src/mame/drivers/psikyo.cpp index 906bd5fd00a..6f9ea7a0934 100644 --- a/src/mame/drivers/psikyo.cpp +++ b/src/mame/drivers/psikyo.cpp @@ -1055,14 +1055,11 @@ static MACHINE_CONFIG_START( sngkace, psikyo_state ) MCFG_VIDEO_START_OVERRIDE(psikyo_state,sngkace) /* sound hardware */ - MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") + MCFG_SPEAKER_STANDARD_MONO("mono") MCFG_SOUND_ADD("ymsnd", YM2610, XTAL_32MHz/4) /* verified on pcb */ MCFG_YM2610_IRQ_HANDLER(INPUTLINE("audiocpu", 0)) - MCFG_SOUND_ROUTE(0, "lspeaker", 1.2) - MCFG_SOUND_ROUTE(0, "rspeaker", 1.2) - MCFG_SOUND_ROUTE(1, "lspeaker", 1.0) - MCFG_SOUND_ROUTE(2, "rspeaker", 1.0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) MACHINE_CONFIG_END @@ -1101,14 +1098,11 @@ static MACHINE_CONFIG_START( gunbird, psikyo_state ) MCFG_VIDEO_START_OVERRIDE(psikyo_state,psikyo) /* sound hardware */ - MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") + MCFG_SPEAKER_STANDARD_MONO("mono") MCFG_SOUND_ADD("ymsnd", YM2610, 8000000) MCFG_YM2610_IRQ_HANDLER(INPUTLINE("audiocpu", 0)) - MCFG_SOUND_ROUTE(0, "lspeaker", 1.2) - MCFG_SOUND_ROUTE(0, "rspeaker", 1.2) - MCFG_SOUND_ROUTE(1, "lspeaker", 1.0) - MCFG_SOUND_ROUTE(2, "rspeaker", 1.0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) MACHINE_CONFIG_END static MACHINE_CONFIG_START( s1945bl, psikyo_state ) /* Bootleg hardware based on the unprotected Japanese Strikers 1945 set */ @@ -1181,12 +1175,11 @@ static MACHINE_CONFIG_START( s1945, psikyo_state ) MCFG_VIDEO_START_OVERRIDE(psikyo_state,psikyo) /* sound hardware */ - MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") + MCFG_SPEAKER_STANDARD_MONO("mono") MCFG_SOUND_ADD("ymf", YMF278B, YMF278B_STD_CLOCK) MCFG_YMF278B_IRQ_HANDLER(INPUTLINE("audiocpu", 0)) - MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) - MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) MACHINE_CONFIG_END diff --git a/src/mame/mess.lst b/src/mame/mess.lst index 188bbdda09d..90d9ecedd9e 100644 --- a/src/mame/mess.lst +++ b/src/mame/mess.lst @@ -1774,6 +1774,9 @@ tmc600s2 //osc1000b nano +// Escola Politecnica da USP (Brazil) +patinho // 1972 Patinho Feio + // MIT tx0_64kw // April 1956 MIT TX-0 (64kw RAM) tx0_8kw // 1962 MIT TX-0 (8kw RAM)