Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Non-working: Zezinho / ITA-II (Brazil, 1961/62) #2771

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions scripts/src/cpu.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1483,6 +1483,22 @@ if (CPUS["PDP1"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/pdp1/tx0dasm.cpp")
end

--------------------------------------------------
-- ZEZINHO2 - ITA - Instituto Tecnológico da Aeronáutica (Brazil)
--@src/devices/cpu/zezinho/zezinho_cpu.h,CPUS["ZEZINHO2"] = true
--------------------------------------------------

if (CPUS["ZEZINHO2"]~=null) then
files {
MAME_DIR .. "src/devices/cpu/zezinho/zezinho.cpp",
MAME_DIR .. "src/devices/cpu/zezinho/zezinho_cpu.h",
}
end

if (CPUS["ZEZINHO2"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/zezinho/zezinho_dasm.cpp")
end

--------------------------------------------------
-- PATINHO FEIO - Escola Politecnica - USP (Brazil)
--@src/devices/cpu/patinhofeio/patinhofeio_cpu.h,CPUS["PATINHOFEIO"] = true
Expand Down
8 changes: 8 additions & 0 deletions scripts/target/mame/mess.lua
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ CPUS["APEXC"] = true
CPUS["CP1610"] = true
CPUS["F8"] = true
CPUS["LH5801"] = true
CPUS["ZEZINHO2"] = true
CPUS["PATINHOFEIO"] = true
CPUS["PDP1"] = true
CPUS["SATURN"] = true
Expand Down Expand Up @@ -1005,6 +1006,7 @@ function linkProjects_mame_mess(_target, _subtarget)
"interton",
"intv",
"isc",
"ita",
"kaypro",
"koei",
"kontron",
Expand Down Expand Up @@ -3255,6 +3257,12 @@ files {
MAME_DIR .. "src/mame/drivers/univac.cpp",
}

createMESSProjects(_target, _subtarget, "ita")
files {
MAME_DIR .. "src/mame/drivers/zezinho.cpp",
MAME_DIR .. "src/mame/includes/zezinho.h",
}

createMESSProjects(_target, _subtarget, "usp")
files {
MAME_DIR .. "src/mame/drivers/patinho_feio.cpp",
Expand Down
123 changes: 123 additions & 0 deletions src/devices/cpu/zezinho/zezinho.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// license:GPL-2.0+
// copyright-holders:Felipe Sanches; Werner Moecke

angelosa marked this conversation as resolved.
Show resolved Hide resolved
#include "emu.h"
#include "zezinho_cpu.h"
#include "debugger.h"
#include "includes/zezinho.h"

#define READ_PROG_BYTE_ZEZINHO(A) (m_program->read_byte(A))
#define WRITE_PROG_BYTE_ZEZINHO(A,V) (m_program->write_byte(A,V))

#define READ_DATA_BYTE_ZEZINHO(A) (m_data->read_byte(A))
#define WRITE_DATA_BYTE_ZEZINHO(A,V) (m_data->write_byte(A,V))

#define READ_DATA_WORD_ZEZINHO(A) ((int)((m_data->read_byte(2*A)<<8) | m_data->read_byte(2*A+1)))
#define WRITE_DATA_WORD_ZEZINHO(A,V) {m_data->write_byte(2*A,V>>8); m_data->write_byte(2*A+1,V&0xFF);}

#define ADDRESS_MASK_4K 0xFFF
#define INCREMENT_PC_4K (m_pc = (m_pc+1) & ADDRESS_MASK_4K)

DEFINE_DEVICE_TYPE(ZEZINHO2_CPU, zezinho_cpu_device, "zezinho2_cpu", "Zezinho (ITA-II) CPU")

//Internal 4k-10bits of RAM
static ADDRESS_MAP_START(datamem_16bit, AS_DATA, /*10*/ 16, zezinho_cpu_device)
AM_RANGE(0x0000, 0x0fff) AM_RAM
ADDRESS_MAP_END

//ROM
static ADDRESS_MAP_START(progmem_16bit, AS_PROGRAM, 16, zezinho_cpu_device)
AM_RANGE(0x0000, 0x0fff) AM_ROM
ADDRESS_MAP_END

zezinho_cpu_device::zezinho_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cpu_device(mconfig, ZEZINHO2_CPU, tag, owner, clock)
, m_data_config("data", ENDIANNESS_BIG, /*10*/ 16, 12, 0, ADDRESS_MAP_NAME(datamem_16bit))
, m_program_config("program", ENDIANNESS_BIG, 16, 12, 0, ADDRESS_MAP_NAME(progmem_16bit))
, m_icount(0)
{
}

device_memory_interface::space_config_vector zezinho_cpu_device::memory_space_config() const
{
return space_config_vector {
std::make_pair(AS_PROGRAM, &m_program_config),
std::make_pair(AS_DATA, &m_data_config)
};
}

void zezinho_cpu_device::device_start()
{
m_program = &space(AS_PROGRAM);
m_data = &space(AS_DATA);

save_item(NAME(m_pc));
save_item(NAME(m_acc));
save_item(NAME(m_addr));
save_item(NAME(m_opcode));

// Register state for debugger
state_add( ZEZINHO_CI, "CI", m_pc ).mask(0xFFF);
state_add( ZEZINHO_ACC, "ACC", m_acc ).mask(0xFFF);
state_add(STATE_GENPC, "GENPC", m_pc).formatstr("0%06O").noshow();
state_add(STATE_GENPCBASE, "CURPC", m_pc).formatstr("0%06O").noshow();

m_icountptr = &m_icount;
}

void zezinho_cpu_device::device_reset()
{
m_pc = 0;
m_acc = 0;
m_run = true;
m_addr = 0;
m_opcode = 0;
}

/* execute instructions on this CPU until icount expires */
void zezinho_cpu_device::execute_run() {
do {
debugger_instruction_hook(this, m_pc);

if (!m_run){
m_icount = 0; /* if processor is stopped, just burn cycles */
} else {
execute_instruction();
m_icount --;
}
}
while (m_icount > 0);
}

#define OPERAND_ADDRESS(operand) (~((m_opcode & 0x0F) << 8 | operand) & 0xFFF)

/* execute one instruction */
void zezinho_cpu_device::execute_instruction()
{
int operand;
m_opcode = READ_PROG_BYTE_ZEZINHO(m_pc); INCREMENT_PC_4K;
operand = READ_PROG_BYTE_ZEZINHO(m_pc); INCREMENT_PC_4K;

switch (m_opcode & 0xF0){
case 0x20: // Sai
printf("Sai: %d\n", READ_DATA_WORD_ZEZINHO(OPERAND_ADDRESS(operand)));
return;
case 0x30: // Armazena
WRITE_DATA_WORD_ZEZINHO(OPERAND_ADDRESS(operand), m_acc);
return;
case 0xD0: // Limpa o acumulador e subtrai
m_acc = -READ_DATA_WORD_ZEZINHO(OPERAND_ADDRESS(operand));
return;
case 0xE0: // Soma
m_acc += READ_DATA_WORD_ZEZINHO(OPERAND_ADDRESS(operand));
return;
default:
printf("unimplemented opcode: 0x%02X\n", m_opcode);
}
}

offs_t zezinho_cpu_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options)
{
extern CPU_DISASSEMBLE( zezinho );
return CPU_DISASSEMBLE_NAME(zezinho)(this, stream, pc, oprom, opram, options);
}
64 changes: 64 additions & 0 deletions src/devices/cpu/zezinho/zezinho_cpu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// license:GPL-2.0+
// copyright-holders:Felipe Sanches
#ifndef MAME_DEVICES_CPU_ZEZINHO_CPU_H
#define MAME_DEVICES_CPU_ZEZINHO_CPU_H

#pragma once

/* register IDs */
enum
{
ZEZINHO_CI=1, ZEZINHO_ACC
};


class zezinho_cpu_device : public cpu_device {
public:
// construction/destruction
zezinho_cpu_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock);

protected:

virtual void execute_run() override;
virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override;

address_space_config m_data_config;
address_space_config m_program_config;

offs_t m_addr;
unsigned char m_opcode;

/* processor registers */
int m_acc; /* accumulator (10 bits) */
unsigned int m_pc; /* program counter (12 bits) */

/* processor state flip-flops */
bool m_run; /* processor is running */

int m_icount;

address_space *m_program;
address_space *m_data;

// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;

// device_execute_interface overrides
virtual uint32_t execute_min_cycles() const override { return 1; }
virtual uint32_t execute_max_cycles() const override { return 2; }

// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;

// device_disasm_interface overrides
virtual uint32_t disasm_min_opcode_bytes() const override { return 2; }
virtual uint32_t disasm_max_opcode_bytes() const override { return 2; }

private:
void execute_instruction();
};

DECLARE_DEVICE_TYPE(ZEZINHO2_CPU, zezinho_cpu_device)

#endif // MAME_DEVICES_CPU_ZEZINHO_CPU_H
80 changes: 80 additions & 0 deletions src/devices/cpu/zezinho/zezinho_dasm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// license:GPL-2.0+
// copyright-holders:Felipe Sanches; Werner Moecke
#include "emu.h"
#include "cpu/zezinho/zezinho_cpu.h"

CPU_DISASSEMBLE(zezinho)
{
int addr;
int value;
switch (oprom[0] & 0xF0) {
case 0x20: // Saída
util::stream_format(stream, "SAIDA");
return 2;
case 0x30: // Armazena
addr = (oprom[0] & 0x0F) << 8 | oprom[1];
util::stream_format(stream, "ARMAZENA (%03X)", ~addr & 0xFFF);
return 2;
case 0x40: // l - Transfira se Acc < 0
//addr = (oprom[0] & 0x0F) << 8 | oprom[1];
util::stream_format(stream, "TRANSFIRA_SE_ACC_<_0");
return 2;
case 0x50: // k - Transfira se Acc > 0
//addr = (oprom[0] & 0x0F) << 8 | oprom[1];
util::stream_format(stream, "TRANSFIRA_SE_ACC_>_0");
return 2;
case 0x60: // j - Transfira se Acc = 0
//
//addr = (oprom[0] & 0x0F) << 8 | oprom[1];
util::stream_format(stream, "TRANSFIRA_SE_ACC_ZERO");
return 2;
case 0x70: // i - Transfira
//
//addr = (oprom[0] & 0x0F) << 8 | oprom[1];
util::stream_format(stream, "TRANSFIRA");
return 2;
case 0x80: // h - Subtração inversa
//
//addr = (oprom[0] & 0x0F) << 8 | oprom[1];
util::stream_format(stream, "SUBTRAÇÂO_INVERSA");
return 2;
case 0x90: // g - Divisão inversa
//
//addr = (oprom[0] & 0x0F) << 8 | oprom[1];
util::stream_format(stream, "DIVISÃO_INVERSA");
return 2;
case 0xa0: // f - Divida
//
//addr = (oprom[0] & 0x0F) << 8 | oprom[1];
util::stream_format(stream, "DIVIDA");
return 2;
case 0xb0: // e - Multiplique
//
//addr = (oprom[0] & 0x0F) << 8 | oprom[1];
util::stream_format(stream, "MULTIPLIQUE");
return 2;
case 0xc0: // d - Subtrai
//
value = (oprom[0] & 0x0F) << 8 | oprom[1];
util::stream_format(stream, "SUBTRAI (%03X)", ~value & 0xFFF);
return 2;
case 0xd0: // c - Limpa acumulador e subtrai
//
value = (oprom[0] & 0x0F) << 8 | oprom[1];
util::stream_format(stream, "LIMPA_ACC_E_SUBTRAI (%03X)", ~value & 0xFFF);
return 2;
case 0xe0: // b - Soma
//
value = (oprom[0] & 0x0F) << 8 | oprom[1];
util::stream_format(stream, "SOMA (%03X)", ~value & 0xFFF);
return 2;
case 0xf0: // a - Limpa acumulador e soma
//
//addr = (oprom[0] & 0x0F) << 8 | oprom[1];
util::stream_format(stream, "LIMPA_ACC_E_SOMA");
return 2;
}

util::stream_format(stream, "illegal instruction");
return 1;
}
47 changes: 47 additions & 0 deletions src/mame/drivers/zezinho.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// license:GPL-2.0+
// copyright-holders:Felipe Sanches; Werner Moecke
/*
Zezinho - Instituto Tecnológico da Aeronáutica (ITA)

Presumably the first computer designed and built in Brazil.
There are 2 variants. The first one, from 1961, is clearly not a turing-complete machine since
it only has got 4 instructions (add, subtract, data input and data output).

The second one, from 1962, was also called ITA-II, and has got 14 instructions including things like branching.
Unfortunately I am unaware of any software for the second iteration.

This driver only emulates the second variant, but runs a demo from the manual of the first one.
While there's now proper artwork, the only useful way to use this driver is by running it with MAME's debugger
to run the example code step-by-step.
Comment on lines +4 to +15
Copy link
Member

@angelosa angelosa Jan 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How this computer (mainframe?) is supposed to run SW, tapes? Punch card? Other?
Feel free to link websites here if you have any.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a very primitive computer. There's almost no info about it. It was probably programmed manually in some very rudimentary way of setting bits. We really lack more detailed docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a wikipedia page about the computer, written in Brazilian Portuguese:
https://pt.wikipedia.org/wiki/Zezinho

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this definitely needs some kind of planning, and a better picture resolution on reference [3] of the link attached for an artwork to happen. I also have concerns as UX standpoint around using a ROM, other than being "technically" wrong I mean.


See also the "Patinho Feio" driver in MAME, for info on another early Brazilian computer (which was
designed a decade later in 1971).
*/

#include "emu.h"
#include "cpu/zezinho/zezinho_cpu.h"
#include "includes/zezinho.h"
//#include "zezinho.lh"

/*
driver init function
*/
DRIVER_INIT_MEMBER(zezinho_state, ita2)
{
}

static MACHINE_CONFIG_START( ita2 )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", ZEZINHO2_CPU, 5000)

// MCFG_DEFAULT_LAYOUT(layout_zezinho)
MACHINE_CONFIG_END

ROM_START( ita2 )
ROM_REGION( 0x1000, "maincpu", 0 ) //Manual de demonstração
ROM_LOAD( "exemplo.rom", 0x000, 0x010, CRC(590b78e9) SHA1(a71e63697068cc167b84802681c65dcbcdd489a5) )
ROM_END

// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS
COMP( 1962, ita2, 0, 0, ita2, 0, zezinho_state, ita2, "ITA - Instituto Tecnologico da Aeronautica (Brazil)", "Zezinho (ITA-II)", MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING )
//COMP( 1961, zezinho, 0, 0, zezinho, 0, zezinho_state, zezinho, "ITA - Instituto Tecnologico da Aeronautica (Brazil)", "Zezinho" , MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING )
23 changes: 23 additions & 0 deletions src/mame/includes/zezinho.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// license:GPL2+
// copyright-holders:Felipe Sanches
#ifndef MAME_INCLUDES_ZEZINHO_H
#define MAME_INCLUDES_ZEZINHO_H

#pragma once

class zezinho_state : public driver_device {
public:
zezinho_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
{ }

DECLARE_DRIVER_INIT(ita2);

protected:
//virtual void machine_start() override;
required_device<zezinho_cpu_device> m_maincpu;
private:
};

#endif // MAME_INCLUDES_ZEZINHO_H