summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Curt Coder <curtcoder@mail.com>2010-10-18 12:13:58 +0000
committer Curt Coder <curtcoder@mail.com>2010-10-18 12:13:58 +0000
commit3c3f26a66ff25f34487261cfa67a79788881af8d (patch)
tree2e8586bd8d91d8e7fefecb0f618b7632b3b9a418
parent40910ec4a6b3a725f65699765e9f0a0c9a85c125 (diff)
Converted the RCA CDP1802 CPU into a C++ device. Refactored cidelsa.c to use the new RCA COSMAC CPU. [Curt Coder]
-rw-r--r--.gitattributes3
-rw-r--r--src/emu/cpu/cosmac/cosdasm.c173
-rw-r--r--src/emu/cpu/cosmac/cosmac.c1173
-rw-r--r--src/emu/cpu/cosmac/cosmac.h414
-rw-r--r--src/emu/cpu/cpu.mak15
-rw-r--r--src/emu/sound/cdp1869.c23
-rw-r--r--src/emu/sound/cdp1869.h3
-rw-r--r--src/mame/drivers/cidelsa.c113
-rw-r--r--src/mame/includes/cidelsa.h5
-rw-r--r--src/mame/mame.mak1
-rw-r--r--src/mame/video/cidelsa.c7
11 files changed, 1857 insertions, 73 deletions
diff --git a/.gitattributes b/.gitattributes
index 15ef1f792dd..7226ac76423 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -65,6 +65,9 @@ src/emu/cpu/cop400/cop400op.c svneol=native#text/plain
src/emu/cpu/cop400/cop410ds.c svneol=native#text/plain
src/emu/cpu/cop400/cop420ds.c svneol=native#text/plain
src/emu/cpu/cop400/cop440ds.c svneol=native#text/plain
+src/emu/cpu/cosmac/cosdasm.c svneol=native#text/plain
+src/emu/cpu/cosmac/cosmac.c svneol=native#text/plain
+src/emu/cpu/cosmac/cosmac.h svneol=native#text/plain
src/emu/cpu/cp1610/1610dasm.c svneol=native#text/plain
src/emu/cpu/cp1610/cp1610.c svneol=native#text/plain
src/emu/cpu/cp1610/cp1610.h svneol=native#text/plain
diff --git a/src/emu/cpu/cosmac/cosdasm.c b/src/emu/cpu/cosmac/cosdasm.c
new file mode 100644
index 00000000000..aa5dbe4a8fd
--- /dev/null
+++ b/src/emu/cpu/cosmac/cosdasm.c
@@ -0,0 +1,173 @@
+/*****************************************************************************
+ *
+ * disasm.c
+ * portable cosmac cdp1802 emulator interface
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * peter.trauner@jk.uni-linz.ac.at
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+
+#include "cosmac.h"
+
+typedef enum
+{
+ Ill,
+ Imm,
+ Imp,
+ Imp2, // lownibble contains register number
+ Imp3, // bit 0,1,2 1..7 contains n0,n1,n2 level
+ Low, // only low byte of address specified
+ Abs
+} Adr;
+
+static const struct { const char *mnemonic; Adr adr; } table[]={
+ { "IDL", Imp }, { "LDN", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "INC", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "DEC", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+
+ { "BR", Low }, { "BQ", Low }, { "BZ", Low }, { "BDF", Low },
+ { "B1", Low }, { "B2", Low }, { "B3", Low }, { "B4", Low },
+ { "SKP", Low }, { "BNQ", Low }, { "BNZ", Low }, { "BNF", Low },
+ { "BN1", Low }, { "BN2", Low }, { "BN3", Low }, { "BN4", Low },
+
+ { "LDA", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "STR", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "IRX", Imp } ,{ "OUT", Imp3},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 } ,{ "INP", Imp3},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "RET", Imp }, { "DIS", Imp }, { "LDXA", Imp }, { "STXD", Imp },
+ { "ADC", Imp }, { "SDB", Imp }, { "SHRC", Imp }, { "SMB", Imp },
+ { "SAV", Imp }, { "MARK", Imp }, { "REQ", Imp }, { "SEQ", Imp },
+ { "ADCI", Imm }, { "SDBI", Imm }, { "SHLC", Imp }, { "SMBI", Imm },
+
+
+ { "GLO", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "GHI", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "PLO", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "PHI", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "LBR", Abs }, { "LBQ", Abs }, { "LBZ", Abs }, { "LBDF", Abs },
+ { "NOP", Imp }, { "LSNQ", Imp }, { "LSNZ", Imp }, { "LSNF", Imp },
+ { "LSKP", Imp }, { "LBNQ", Abs }, { "LBNZ", Abs }, { "LBNF", Abs },
+ { "LSIE", Imp }, { "LSQ", Imp }, { "LSZ", Imp }, { "LSDF", Imp },
+
+ { "SEP", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "SEX", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "LDX", Imp }, { "OR", Imp }, { "AND", Imp }, { "XOR", Imp },
+ { "ADD", Imp }, { "SD", Imp }, { "SHR", Imp }, { "SM", Imp },
+ { "LDI", Imm }, { "ORI", Imm }, { "ANI", Imm }, { "XRI", Imm },
+ { "ADI", Imm }, { "SDI", Imm }, { "SHL", Imp }, { "SMI", Imm },
+
+};
+
+CPU_DISASSEMBLE( cosmac )
+{
+ UINT32 flags = 0;
+ int oldpc = pc;
+ int oper;
+ UINT16 absolut;
+ oldpc&=0xffff;
+ pc=oldpc;
+ oper=oprom[pc++ - oldpc];
+
+ switch(oper&0xf0) {
+ case 0:
+ if (oper==0) {
+ sprintf(buffer,"%-5s",table[oper].mnemonic);
+ } else {
+ sprintf(buffer,"%-5sR%.1x",table[(oper&0xf0)|1].mnemonic, oper&0x0f);
+ }
+ break;
+ case 0xd0:
+ flags = DASMFLAG_STEP_OVER;
+ /* fall through */
+ case 0x10:
+ case 0x20:
+ case 0x40:
+ case 0x50:
+ case 0x80:
+ case 0x90:
+ case 0xa0:
+ case 0xb0:
+ case 0xe0:
+ sprintf(buffer,"%-5sR%.1x",table[oper&0xf0].mnemonic, oper&0x0f);
+ break;
+ default:
+ switch(oper&0xf8) {
+ case 0x60:
+ if (oper==0x60) {
+ sprintf(buffer,"%-5s",table[oper].mnemonic);
+ } else {
+ sprintf(buffer,"%-5s%d",table[(oper&0xf8)|1].mnemonic, oper&0x7);
+ }
+ break;
+ case 0x68:
+ sprintf(buffer,"%-5s%d",table[(oper&0xf8)|1].mnemonic, oper&0x7);
+ break;
+ default:
+ switch (table[oper].adr) {
+ case Imp:
+ sprintf(buffer,"%-5s",table[oper].mnemonic);
+ if (oper == 0x70 || oper == 0x71)
+ flags = DASMFLAG_STEP_OUT;
+ break;
+ case Imm:
+ sprintf(buffer,"%-5s#%.2x",table[oper].mnemonic,oprom[pc++ - oldpc]);
+ break;
+ case Low:
+ absolut=oprom[pc++ - oldpc];
+ absolut|=pc&0xff00;
+ sprintf(buffer,"%-5s%.4x",table[oper].mnemonic,absolut);
+ break;
+ case Abs:
+ absolut=oprom[pc++ - oldpc]<<8;
+ absolut|=oprom[pc++ - oldpc];
+ sprintf(buffer,"%-5s%.4x",table[oper].mnemonic,absolut);
+ break;
+ default:
+ sprintf(buffer,"%-5s%.2x","ill",oper);
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ return (pc-oldpc) | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/src/emu/cpu/cosmac/cosmac.c b/src/emu/cpu/cosmac/cosmac.c
new file mode 100644
index 00000000000..bd8d1b21bba
--- /dev/null
+++ b/src/emu/cpu/cosmac/cosmac.c
@@ -0,0 +1,1173 @@
+/**********************************************************************
+
+ RCA "COSMAC" CPU emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "cosmac.h"
+
+
+/*
+
+ TODO:
+
+ - debugger cursor is not on R(P)
+ - divide clock by 8
+ - min cycles -> 2 and 3
+
+*/
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type COSMAC = cosmac_device_config::static_alloc_device_config;
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+#define CLOCKS_RESET 8
+#define CLOCKS_INIT 8 // really 9, but needs to be 8 to synchronize cdp1861 video timings
+#define CLOCKS_FETCH 8
+#define CLOCKS_EXECUTE 8
+#define CLOCKS_DMA 8
+#define CLOCKS_INTERRUPT 8
+
+const cosmac_state_code COSMAC_STATE_CODE[] =
+{
+ COSMAC_STATE_CODE_S0_FETCH, // COSMAC_STATE_0_FETCH
+ COSMAC_STATE_CODE_S1_EXECUTE, // COSMAC_STATE_1_RESET
+ COSMAC_STATE_CODE_S1_EXECUTE, // COSMAC_STATE_1_INIT
+ COSMAC_STATE_CODE_S1_EXECUTE, // COSMAC_STATE_1_EXECUTE
+ COSMAC_STATE_CODE_S2_DMA, // COSMAC_STATE_2_DMA_IN
+ COSMAC_STATE_CODE_S2_DMA, // COSMAC_STATE_2_DMA_OUT
+ COSMAC_STATE_CODE_S3_INTERRUPT // COSMAC_STATE_3_INT
+};
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define OPCODE_R(addr) read_opcode(addr)
+#define RAM_R(addr) read_byte(addr)
+#define RAM_W(addr, data) write_byte(addr, data)
+#define IO_R(addr) read_io_byte(addr)
+#define IO_W(addr, data) write_io_byte(addr, data)
+
+#define P m_p
+#define X m_x
+#define D m_d
+#define B m_b
+#define T m_t
+#define R m_r
+#define DF m_df
+#define IE m_ie
+#define Q m_q
+#define N m_n
+#define I m_i
+#define EF m_ef
+
+#define GET_FLAGS() ((m_df << 2) | (m_ie << 1) | m_q)
+
+#define SET_FLAGS(v) do { \
+ m_df = BIT(v, 2); \
+ m_ie = BIT(v, 1); \
+ m_q = BIT(v, 0); \
+ } while (0);
+
+
+
+//**************************************************************************
+// STATIC OPCODE TABLES
+//**************************************************************************
+
+const cosmac_device::ophandler cosmac_device::s_opcodetable[256] =
+{
+ &cosmac_device::idl, &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn,
+ &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn,
+ &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn,
+ &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn,
+
+ &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc,
+ &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc,
+ &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc,
+ &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc,
+
+ &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec,
+ &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec,
+ &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec,
+ &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec,
+
+ &cosmac_device::br, &cosmac_device::bq, &cosmac_device::bz, &cosmac_device::bdf,
+ &cosmac_device::b, &cosmac_device::b, &cosmac_device::b, &cosmac_device::b,
+ &cosmac_device::nbr, &cosmac_device::bnq, &cosmac_device::bnz, &cosmac_device::bnf,
+ &cosmac_device::bn, &cosmac_device::bn, &cosmac_device::bn, &cosmac_device::bn,
+
+ &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda,
+ &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda,
+ &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda,
+ &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda,
+
+ &cosmac_device::str, &cosmac_device::str, &cosmac_device::str, &cosmac_device::str,
+ &cosmac_device::str, &cosmac_device::str, &cosmac_device::str, &cosmac_device::str,
+ &cosmac_device::str, &cosmac_device::str, &cosmac_device::str, &cosmac_device::str,
+ &cosmac_device::str, &cosmac_device::str, &cosmac_device::str, &cosmac_device::str,
+
+ &cosmac_device::irx, &cosmac_device::out, &cosmac_device::out, &cosmac_device::out,
+ &cosmac_device::out, &cosmac_device::out, &cosmac_device::out, &cosmac_device::out,
+ &cosmac_device::inp, &cosmac_device::inp, &cosmac_device::inp, &cosmac_device::inp,
+ &cosmac_device::inp, &cosmac_device::inp, &cosmac_device::inp, &cosmac_device::inp,
+
+ &cosmac_device::ret, &cosmac_device::dis, &cosmac_device::ldxa, &cosmac_device::stxd,
+ &cosmac_device::adc, &cosmac_device::sdb, &cosmac_device::shrc, &cosmac_device::smb,
+ &cosmac_device::sav, &cosmac_device::mark, &cosmac_device::req, &cosmac_device::seq,
+ &cosmac_device::adci, &cosmac_device::sdbi, &cosmac_device::shlc, &cosmac_device::smbi,
+
+ &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo,
+ &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo,
+ &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo,
+ &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo,
+
+ &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi,
+ &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi,
+ &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi,
+ &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi,
+
+ &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo,
+ &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo,
+ &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo,
+ &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo,
+
+ &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi,
+ &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi,
+ &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi,
+ &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi,
+
+ &cosmac_device::lbr, &cosmac_device::lbq, &cosmac_device::lbz, &cosmac_device::lbdf,
+ &cosmac_device::nop, &cosmac_device::lsnq, &cosmac_device::lsnz, &cosmac_device::lsnf,
+ &cosmac_device::nlbr, &cosmac_device::lbnq, &cosmac_device::lbnz, &cosmac_device::lbnf,
+ &cosmac_device::lsie, &cosmac_device::lsq, &cosmac_device::lsz, &cosmac_device::lsdf,
+
+ &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep,
+ &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep,
+ &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep,
+ &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep,
+
+ &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex,
+ &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex,
+ &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex,
+ &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex,
+
+ &cosmac_device::ldx, &cosmac_device::_or, &cosmac_device::_and, &cosmac_device::_xor,
+ &cosmac_device::add, &cosmac_device::sd, &cosmac_device::shr, &cosmac_device::sm,
+ &cosmac_device::ldi, &cosmac_device::ori, &cosmac_device::ani, &cosmac_device::xri,
+ &cosmac_device::adi, &cosmac_device::sdi, &cosmac_device::shl, &cosmac_device::smi
+};
+
+
+
+//**************************************************************************
+// COSMAC DEVICE CONFIG
+//**************************************************************************
+
+//-------------------------------------------------
+// cosmac_device_config - constructor
+//-------------------------------------------------
+
+cosmac_device_config::cosmac_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock)
+ : cpu_device_config(mconfig, static_alloc_device_config, "COSMAC", tag, owner, clock),
+ m_program_config("program", ENDIANNESS_LITTLE, 8, 16),
+ m_io_config("io", ENDIANNESS_LITTLE, 8, 3)
+{
+}
+
+
+//-------------------------------------------------
+// static_alloc_device_config - allocate a new
+// configuration object
+//-------------------------------------------------
+
+device_config *cosmac_device_config::static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock)
+{
+ return global_alloc(cosmac_device_config(mconfig, tag, owner, clock));
+}
+
+
+//-------------------------------------------------
+// alloc_device - allocate a new device object
+//-------------------------------------------------
+
+device_t *cosmac_device_config::alloc_device(running_machine &machine) const
+{
+ return auto_alloc(&machine, cosmac_device(machine, *this));
+}
+
+
+//-------------------------------------------------
+// execute_min_cycles - return minimum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 cosmac_device_config::execute_min_cycles() const
+{
+ return 8 * 2;
+}
+
+
+//-------------------------------------------------
+// execute_max_cycles - return maximum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 cosmac_device_config::execute_max_cycles() const
+{
+ return 8 * 3;
+}
+
+
+//-------------------------------------------------
+// execute_input_lines - return the number of
+// input/interrupt lines
+//-------------------------------------------------
+
+UINT32 cosmac_device_config::execute_input_lines() const
+{
+ return 7;
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return the configuration
+// of the specified address space, or NULL if
+// the space doesn't exist
+//-------------------------------------------------
+
+const address_space_config *cosmac_device_config::memory_space_config(int spacenum) const
+{
+ switch (spacenum)
+ {
+ case AS_PROGRAM:
+ return &m_program_config;
+
+ case AS_IO:
+ return &m_io_config;
+
+ default:
+ return NULL;
+ }
+}
+
+
+//-------------------------------------------------
+// disasm_min_opcode_bytes - return the length
+// of the shortest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 cosmac_device_config::disasm_min_opcode_bytes() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// disasm_max_opcode_bytes - return the length
+// of the longest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 cosmac_device_config::disasm_max_opcode_bytes() const
+{
+ return 3;
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void cosmac_device_config::device_config_complete()
+{
+ // inherit a copy of the static data
+ const cosmac_interface *intf = reinterpret_cast<const cosmac_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<cosmac_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_in_wait_func, 0, sizeof(m_in_wait_func));
+ memset(&m_in_clear_func, 0, sizeof(m_in_clear_func));
+ // TODO: clear ef1-4
+ memset(&m_out_q_func, 0, sizeof(m_out_q_func));
+ memset(&m_in_dma_func, 0, sizeof(m_in_dma_func));
+ memset(&m_out_dma_func, 0, sizeof(m_out_dma_func));
+ m_out_sc_func = NULL;
+ memset(&m_out_tpa_func, 0, sizeof(m_out_tpa_func));
+ memset(&m_out_tpb_func, 0, sizeof(m_out_tpb_func));
+ }
+}
+
+
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// cosmac_device - constructor
+//-------------------------------------------------
+
+cosmac_device::cosmac_device(running_machine &_machine, const cosmac_device_config &config)
+ : cpu_device(_machine, config),
+ m_op(0),
+ m_state(COSMAC_STATE_1_RESET),
+ m_mode(COSMAC_MODE_RESET),
+ m_irq(0),
+ m_dmain(0),
+ m_dmaout(0),
+ m_program(NULL),
+ m_io(NULL),
+ m_direct(NULL),
+ m_config(config)
+{
+ for (int i = 0; i < 4; i++)
+ EF[i] = 0;
+}
+
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void cosmac_device::device_start()
+{
+ // get our address spaces
+ m_program = space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+ m_io = space(AS_IO);
+
+ // register our state for the debugger
+ state_add(STATE_GENPC, "GENPC", R[P]).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_flagsio).mask(0x7).callimport().callexport().noshow().formatstr("%3s");
+
+ state_add(COSMAC_P, "P", m_p).mask(0xf);
+ state_add(COSMAC_X, "X", m_x).mask(0xf);
+ state_add(COSMAC_D, "D", m_d);
+ state_add(COSMAC_B, "B", m_b);
+ state_add(COSMAC_T, "T", m_t);
+
+ state_add(COSMAC_I, "I", m_i).mask(0xf);
+ state_add(COSMAC_N, "N", m_n).mask(0xf);
+
+ astring tempstr;
+ for (int regnum = 0; regnum < 16; regnum++)
+ state_add(COSMAC_R0 + regnum, tempstr.format("R%x", regnum), m_r[regnum]);
+
+ state_add(COSMAC_DF, "DF", m_df).mask(0x1).noshow();
+ state_add(COSMAC_IE, "IE", m_ie).mask(0x1).noshow();
+ state_add(COSMAC_Q, "Q", m_q).mask(0x1).noshow();
+
+ // resolve callbacks
+ devcb_resolve_read_line(&m_in_wait_func, &m_config.m_in_wait_func, this);
+ devcb_resolve_read_line(&m_in_clear_func, &m_config.m_in_clear_func, this);
+ devcb_resolve_read_line(&m_in_ef_func[0], &m_config.m_in_ef1_func, this);
+ devcb_resolve_read_line(&m_in_ef_func[1], &m_config.m_in_ef2_func, this);
+ devcb_resolve_read_line(&m_in_ef_func[2], &m_config.m_in_ef3_func, this);
+ devcb_resolve_read_line(&m_in_ef_func[3], &m_config.m_in_ef4_func, this);
+ devcb_resolve_write_line(&m_out_q_func, &m_config.m_out_q_func, this);
+ devcb_resolve_read8(&m_in_dma_func, &m_config.m_in_dma_func, this);
+ devcb_resolve_write8(&m_out_dma_func, &m_config.m_out_dma_func, this);
+ m_out_sc_func = m_config.m_out_sc_func;
+ devcb_resolve_write_line(&m_out_tpa_func, &m_config.m_out_tpa_func, this);
+ devcb_resolve_write_line(&m_out_tpb_func, &m_config.m_out_tpb_func, this);
+
+ // register our state for saving
+ state_save_register_device_item(this, 0, m_op);
+ state_save_register_device_item(this, 0, m_flagsio);
+ state_save_register_device_item(this, 0, m_state);
+ state_save_register_device_item(this, 0, m_mode);
+ state_save_register_device_item(this, 0, m_pmode);
+ state_save_register_device_item(this, 0, m_irq);
+ state_save_register_device_item(this, 0, m_dmain);
+ state_save_register_device_item(this, 0, m_dmaout);
+ state_save_register_device_item_array(this, 0, m_ef);
+ state_save_register_device_item(this, 0, m_d);
+ state_save_register_device_item(this, 0, m_b);
+ state_save_register_device_item_array(this, 0, m_r);
+ state_save_register_device_item(this, 0, m_p);
+ state_save_register_device_item(this, 0, m_x);
+ state_save_register_device_item(this, 0, m_n);
+ state_save_register_device_item(this, 0, m_i);
+ state_save_register_device_item(this, 0, m_t);
+ state_save_register_device_item(this, 0, m_df);
+ state_save_register_device_item(this, 0, m_ie);
+ state_save_register_device_item(this, 0, m_q);
+ state_save_register_device_item(this, 0, m_icount);
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+}
+
+
+//-------------------------------------------------
+// device_reset - reset the device
+//-------------------------------------------------
+
+void cosmac_device::device_reset()
+{
+}
+
+
+//-------------------------------------------------
+// state_import - import state into the device,
+// after it has been set
+//-------------------------------------------------
+
+void cosmac_device::state_import(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ SET_FLAGS(m_flagsio);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_export - export state from the device,
+// to a known location where it can be read
+//-------------------------------------------------
+
+void cosmac_device::state_export(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ m_flagsio = GET_FLAGS();
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void cosmac_device::state_string_export(const device_state_entry &entry, astring &string)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c",
+ m_df ? 'D' : '.',
+ m_ie ? 'I' : '.',
+ m_q ? 'Q' : '.');
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// disasm_disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+offs_t cosmac_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( cosmac );
+ return CPU_DISASSEMBLE_NAME(cosmac)(NULL, buffer, pc, oprom, opram, 0);
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// read_opcode - read an opcode at the given address
+//-------------------------------------------------
+
+inline UINT8 cosmac_device::read_opcode(offs_t pc)
+{
+ return m_direct->read_decrypted_byte(pc);
+}
+
+
+//-------------------------------------------------
+// read_byte - read a byte at the given address
+//-------------------------------------------------
+
+inline UINT8 cosmac_device::read_byte(offs_t address)
+{
+ return m_program->read_byte(address);
+}
+
+
+//-------------------------------------------------
+// read_io_byte - read an I/O byte at the given
+// address
+//-------------------------------------------------
+
+inline UINT8 cosmac_device::read_io_byte(offs_t address)
+{
+ return m_io->read_byte(address);
+}
+
+
+//-------------------------------------------------
+// write_byte - write a byte at the given address
+//-------------------------------------------------
+
+inline void cosmac_device::write_byte(offs_t address, UINT8 data)
+{
+ m_program->write_byte(address, data);
+}
+
+
+//-------------------------------------------------
+// write_io_byte - write an I/O byte at the given
+// address
+//-------------------------------------------------
+
+inline void cosmac_device::write_io_byte(offs_t address, UINT8 data)
+{
+ m_io->write_byte(address, data);
+}
+
+
+
+//**************************************************************************
+// CORE EXECUTION
+//**************************************************************************
+
+//-------------------------------------------------
+// execute_set_input -
+//-------------------------------------------------
+
+void cosmac_device::execute_set_input(int inputnum, int state)
+{
+ switch (inputnum)
+ {
+ case COSMAC_INPUT_LINE_INT:
+ m_irq = state;
+ break;
+
+ case COSMAC_INPUT_LINE_DMAIN:
+ m_dmain = state;
+ break;
+
+ case COSMAC_INPUT_LINE_DMAOUT:
+ m_dmaout = state;
+ break;
+
+ case COSMAC_INPUT_LINE_EF1:
+ case COSMAC_INPUT_LINE_EF2:
+ case COSMAC_INPUT_LINE_EF3:
+ case COSMAC_INPUT_LINE_EF4:
+ EF[inputnum - COSMAC_INPUT_LINE_EF1] = state;
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// execute_run -
+//-------------------------------------------------
+
+void cosmac_device::execute_run()
+{
+ do
+ {
+ sample_wait_clear();
+
+ switch (m_mode)
+ {
+ case COSMAC_MODE_LOAD:
+ if (m_pmode == COSMAC_MODE_RESET)
+ {
+ m_pmode = COSMAC_MODE_LOAD;
+
+ // execute initialization cycle
+ m_state = COSMAC_STATE_1_INIT;
+ run();
+
+ // next state is IDLE
+ m_state = COSMAC_STATE_1_EXECUTE;
+ }
+ else
+ {
+ // idle
+ m_op = 0;
+ I = 0;
+ N = 0;
+ run();
+ }
+ break;
+
+ case COSMAC_MODE_RESET:
+ m_state = COSMAC_STATE_1_RESET;
+ run();
+ break;
+
+ case COSMAC_MODE_PAUSE:
+ m_icount--;
+ break;
+
+ case COSMAC_MODE_RUN:
+ switch (m_pmode)
+ {
+ case COSMAC_MODE_LOAD:
+ // RUN mode cannot be initiated from LOAD mode
+ logerror("COSMAC '%s' Tried to initiate RUN mode from LOAD mode\n", tag());
+ m_mode = COSMAC_MODE_LOAD;
+ break;
+
+ case COSMAC_MODE_RESET:
+ m_pmode = COSMAC_MODE_RUN;
+ m_state = COSMAC_STATE_1_INIT;
+ run();
+ break;
+
+ case COSMAC_MODE_PAUSE:
+ m_pmode = COSMAC_MODE_RUN;
+ m_state = COSMAC_STATE_0_FETCH;
+ run();
+ break;
+
+ case COSMAC_MODE_RUN:
+ run();
+ break;
+ }
+ break;
+ }
+ }
+ while (m_icount > 0);
+}
+
+
+//-------------------------------------------------
+// run - run the CPU state machine
+//-------------------------------------------------
+
+inline void cosmac_device::run()
+{
+ output_state_code();
+
+ switch (m_state)
+ {
+ case COSMAC_STATE_0_FETCH:
+ fetch_instruction();
+ break;
+
+ case COSMAC_STATE_1_RESET:
+ reset();
+ debug();
+ break;
+
+ case COSMAC_STATE_1_INIT:
+ initialize();
+ debug();
+ break;
+
+ case COSMAC_STATE_1_EXECUTE:
+ sample_ef_lines();
+ execute_instruction();
+ debug();
+ break;
+
+ case COSMAC_STATE_2_DMA_IN:
+ dma_input();
+ break;
+
+ case COSMAC_STATE_2_DMA_OUT:
+ dma_output();
+ break;
+
+ case COSMAC_STATE_3_INT:
+ interrupt();
+ debug();
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// debug - hook into debugger
+//-------------------------------------------------
+
+inline void cosmac_device::debug()
+{
+ if (device_t::m_machine.debug_flags & DEBUG_FLAG_ENABLED)
+ {
+ debugger_instruction_hook(this, R[P]);
+ }
+}
+
+
+//-------------------------------------------------
+// sample_wait_clear - sample wait/clear lines
+//-------------------------------------------------
+
+inline void cosmac_device::sample_wait_clear()
+{
+ int wait = devcb_call_read_line(&m_in_wait_func);
+ int clear = devcb_call_read_line(&m_in_clear_func);
+
+ m_pmode = m_mode;
+ m_mode = (cosmac_mode) ((clear << 1) | wait);
+}
+
+
+//-------------------------------------------------
+// sample_ef_lines - sample EF input lines
+//-------------------------------------------------
+
+inline void cosmac_device::sample_ef_lines()
+{
+ for (int i = 0; i < 4; i++)
+ {
+ if (m_in_ef_func[i].target != NULL)
+ {
+ EF[i] = devcb_call_read_line(&m_in_ef_func[i]);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// output_state_code - output state code
+//-------------------------------------------------
+
+inline void cosmac_device::output_state_code()
+{
+ if (m_out_sc_func != NULL)
+ {
+ m_out_sc_func(this, COSMAC_STATE_CODE[m_state]);
+ }
+}
+
+
+//-------------------------------------------------
+// set_q_flag - set Q flag state and output it
+//-------------------------------------------------
+
+inline void cosmac_device::set_q_flag(int state)
+{
+ Q = state;
+
+ devcb_call_write_line(&m_out_q_func, Q);
+}
+
+
+//-------------------------------------------------
+// fetch_instruction - fetch instruction from
+// the program memory
+//-------------------------------------------------
+
+inline void cosmac_device::fetch_instruction()
+{
+ // instruction fetch
+ m_op = read_opcode(R[P]);
+ R[P]++;
+
+ I = m_op >> 4;
+ N = m_op & 0x0f;
+
+ m_icount -= CLOCKS_FETCH;
+
+ m_state = COSMAC_STATE_1_EXECUTE;
+}
+
+
+//-------------------------------------------------
+// reset - handle reset state
+//-------------------------------------------------
+
+inline void cosmac_device::reset()
+{
+ m_op = 0;
+ I = 0;
+ N = 0;
+ Q = 0;
+ IE = 1;
+
+ m_icount -= CLOCKS_RESET;
+}
+
+
+//-------------------------------------------------
+// initialize - handle initialization state
+//-------------------------------------------------
+
+inline void cosmac_device::initialize()
+{
+ X = 0;
+ P = 0;
+ R[0] = 0;
+
+ m_icount -= CLOCKS_INIT;
+
+ if (m_dmain)
+ {
+ m_state = COSMAC_STATE_2_DMA_IN;
+ }
+ else if (m_dmaout)
+ {
+ m_state = COSMAC_STATE_2_DMA_OUT;
+ }
+ else
+ {
+ m_state = COSMAC_STATE_0_FETCH;
+ }
+}
+
+
+//-------------------------------------------------
+// execute_instruction - execute instruction
+//-------------------------------------------------
+
+inline void cosmac_device::execute_instruction()
+{
+ // parse the instruction
+ (this->*s_opcodetable[m_op])();
+
+ m_icount -= CLOCKS_EXECUTE;
+
+ if (m_dmain)
+ {
+ m_state = COSMAC_STATE_2_DMA_IN;
+ }
+ else if (m_dmaout)
+ {
+ m_state = COSMAC_STATE_2_DMA_OUT;
+ }
+ else if (IE && m_irq)
+ {
+ m_state = COSMAC_STATE_3_INT;
+ }
+ else if ((I > 0) || (N > 0)) // not idling
+ {
+ m_state = COSMAC_STATE_0_FETCH;
+ }
+}
+
+
+//-------------------------------------------------
+// dma_input - handle DMA input state
+//-------------------------------------------------
+
+inline void cosmac_device::dma_input()
+{
+ RAM_W(R[0], devcb_call_read8(&m_in_dma_func, R[0]));
+
+ R[0]++;
+
+ m_icount -= CLOCKS_DMA;
+
+ if (m_dmain)
+ {
+ m_state = COSMAC_STATE_2_DMA_IN;
+ }
+ else if (m_dmaout)
+ {
+ m_state = COSMAC_STATE_2_DMA_OUT;
+ }
+ else if (IE && m_irq)
+ {
+ m_state = COSMAC_STATE_3_INT;
+ }
+ else if (m_mode == COSMAC_MODE_LOAD)
+ {
+ m_state = COSMAC_STATE_1_EXECUTE;
+ }
+ else
+ {
+ m_state = COSMAC_STATE_0_FETCH;
+ }
+}
+
+
+//-------------------------------------------------
+// dma_output - handle DMA output state
+//-------------------------------------------------
+
+inline void cosmac_device::dma_output()
+{
+ devcb_call_write8(&m_out_dma_func, R[0], RAM_R(R[0]));
+
+ R[0]++;
+
+ m_icount -= CLOCKS_DMA;
+
+ if (m_dmain)
+ {
+ m_state = COSMAC_STATE_2_DMA_IN;
+ }
+ else if (m_dmaout)
+ {
+ m_state = COSMAC_STATE_2_DMA_OUT;
+ }
+ else if (IE && m_irq)
+ {
+ m_state = COSMAC_STATE_3_INT;
+ }
+ else
+ {
+ m_state = COSMAC_STATE_0_FETCH;
+ }
+}
+
+
+//-------------------------------------------------
+// interrupt - handle interrupt state
+//-------------------------------------------------
+
+inline void cosmac_device::interrupt()
+{
+ T = (X << 4) | P;
+ X = 2;
+ P = 1;
+ IE = 0;
+
+ m_icount -= CLOCKS_INTERRUPT;
+
+ if (m_dmain)
+ {
+ m_state = COSMAC_STATE_2_DMA_IN;
+ }
+ else if (m_dmaout)
+ {
+ m_state = COSMAC_STATE_2_DMA_OUT;
+ }
+ else
+ {
+ m_state = COSMAC_STATE_0_FETCH;
+ }
+}
+
+
+
+//**************************************************************************
+// OPCODE IMPLEMENTATIONS
+//**************************************************************************
+
+// memory reference opcode handlers
+void cosmac_device::ldn() { D = RAM_R(R[N]); }
+void cosmac_device::lda() { D = RAM_R(R[N]); R[N]++; }
+void cosmac_device::ldx() { D = RAM_R(R[X]); }
+void cosmac_device::ldxa() { D = RAM_R(R[X]); R[X]++; }
+void cosmac_device::ldi() { D = RAM_R(R[P]); R[P]++; }
+void cosmac_device::str() { RAM_W(R[N], D); }
+void cosmac_device::stxd() { RAM_W(R[X], D); R[X]--; }
+
+// register operations opcode handlers
+void cosmac_device::inc() { R[N]++; }
+void cosmac_device::dec() { R[N]--; }
+void cosmac_device::irx() { R[X]++; }
+void cosmac_device::glo() { D = R[N] & 0xff; }
+void cosmac_device::plo() { R[N] = (R[N] & 0xff00) | D; }
+void cosmac_device::ghi() { D = R[N] >> 8; }
+void cosmac_device::phi() { R[N] = (D << 8) | (R[N] & 0xff); }
+
+// logic operations opcode handlers
+void cosmac_device::_or() { D = RAM_R(R[X]) | D; }
+void cosmac_device::ori() { D = RAM_R(R[P]) | D; R[P]++; }
+void cosmac_device::_xor() { D = RAM_R(R[X]) ^ D; }
+void cosmac_device::xri() { D = RAM_R(R[P]) ^ D; R[P]++; }
+void cosmac_device::_and() { D = RAM_R(R[X]) & D; }
+void cosmac_device::ani() { D = RAM_R(R[P]) & D; R[P]++; }
+void cosmac_device::shr() { DF = BIT(D, 0); D >>= 1; }
+void cosmac_device::shrc() { int b = DF; DF = BIT(D, 0); D >>= 1; D |= b << 7; }
+void cosmac_device::shl() { DF = BIT(D, 7); D <<= 1; }
+void cosmac_device::shlc() { int b = DF; DF = BIT(D, 7); D <<= 1; D |= b; }
+
+// arithmetic operations opcode handlers
+void cosmac_device::add(int left, int right)
+{
+ int result = left + right;
+
+ D = result & 0xff;
+ DF = result > 0xff;
+}
+
+void cosmac_device::add_with_carry(int left, int right)
+{
+ int result = left + right + DF;
+
+ D = result & 0xff;
+ DF = result > 0xff;
+}
+
+void cosmac_device::subtract(int left, int right)
+{
+ int result = left + (right ^ 0xff) + 1;
+
+ D = result & 0xff;
+ DF = result > 0xff;
+}
+
+void cosmac_device::subtract_with_borrow(int left, int right)
+{
+ int result = left + (right ^ 0xff) + DF;
+
+ D = result & 0xff;
+ DF = result > 0xff;
+}
+
+void cosmac_device::add() { add(RAM_R(R[X]), D); }
+void cosmac_device::adi() { add(RAM_R(R[P]), D); R[P]++; }
+void cosmac_device::adc() { add_with_carry(RAM_R(R[X]), D); }
+void cosmac_device::adci() { add_with_carry(RAM_R(R[P]), D); R[P]++; }
+void cosmac_device::sd() { subtract(RAM_R(R[X]), D); }
+void cosmac_device::sdi() { subtract(RAM_R(R[P]), D); R[P]++; }
+void cosmac_device::sdb() { subtract_with_borrow(RAM_R(R[X]), D); }
+void cosmac_device::sdbi() { subtract_with_borrow(RAM_R(R[P]), D); R[P]++; }
+void cosmac_device::sm() { subtract(D, RAM_R(R[X])); }
+void cosmac_device::smi() { subtract(D, RAM_R(R[P])); R[P]++; }
+void cosmac_device::smb() { subtract_with_borrow(D, RAM_R(R[X])); }
+void cosmac_device::smbi() { subtract_with_borrow(D, RAM_R(R[P])); R[P]++; }
+
+// short branch instructions opcode handlers
+void cosmac_device::short_branch(int taken)
+{
+ if (taken)
+ {
+ R[P] = (R[P] & 0xff00) | OPCODE_R(R[P]);
+ }
+ else
+ {
+ R[P]++;
+ }
+}
+
+void cosmac_device::br() { short_branch(1); }
+void cosmac_device::nbr() { short_branch(0); }
+void cosmac_device::bz() { short_branch(D == 0); }
+void cosmac_device::bnz() { short_branch(D != 0); }
+void cosmac_device::bdf() { short_branch(DF); }
+void cosmac_device::bnf() { short_branch(!DF); }
+void cosmac_device::bq() { short_branch(Q); }
+void cosmac_device::bnq() { short_branch(!Q); }
+void cosmac_device::b() { short_branch(EF[N & 0x03]); }
+void cosmac_device::bn() { short_branch(!EF[N & 0x03]); }
+
+// long branch instructions opcode handlers
+void cosmac_device::long_branch(int taken)
+{
+ if (taken)
+ {
+ // S1#1
+ B = OPCODE_R(R[P]++);
+
+ // S1#2
+ R[P] = (B << 8) | OPCODE_R(R[P]);
+ }
+ else
+ {
+ // S1#1
+ R[P]++;
+
+ // S1#2
+ R[P]++;
+ }
+
+ m_icount -= CLOCKS_EXECUTE;
+}
+
+void cosmac_device::lbr() { long_branch(1); }
+void cosmac_device::nlbr() { long_skip(1); }
+void cosmac_device::lbz() { long_branch(D == 0); }
+void cosmac_device::lbnz() { long_branch(D != 0); }
+void cosmac_device::lbdf() { long_branch(DF); }
+void cosmac_device::lbnf() { long_branch(!DF); }
+void cosmac_device::lbq() { long_branch(Q); }
+void cosmac_device::lbnq() { long_branch(!Q); }
+
+// skip instructions opcode handlers
+void cosmac_device::long_skip(int taken)
+{
+ if (taken)
+ {
+ // S1#1
+ R[P]++;
+
+ // S1#2
+ R[P]++;
+ }
+
+ m_icount -= CLOCKS_EXECUTE;
+}
+
+void cosmac_device::lsz() { long_skip(D == 0); }
+void cosmac_device::lsnz() { long_skip(D != 0); }
+void cosmac_device::lsdf() { long_skip(DF); }
+void cosmac_device::lsnf() { long_skip(!DF); }
+void cosmac_device::lsq() { long_skip(Q); }
+void cosmac_device::lsnq() { long_skip(!Q); }
+void cosmac_device::lsie() { long_skip(IE); }
+
+// control instructions opcode handlers
+void cosmac_device::idl() { /* idle */ }
+void cosmac_device::nop() { m_icount -= CLOCKS_EXECUTE; }
+void cosmac_device::sep() { P = N; }
+void cosmac_device::sex() { X = N; }
+void cosmac_device::seq() { set_q_flag(1); }
+void cosmac_device::req() { set_q_flag(0); }
+void cosmac_device::sav() { RAM_W(R[X], T); }
+
+void cosmac_device::mark()
+{
+ T = (X << 4) | P;
+ RAM_W(R[2], T);
+ X = P;
+ R[2]--;
+}
+
+void cosmac_device::return_from_interrupt(int ie)
+{
+ UINT8 data = RAM_R(R[X]);
+ R[X]++;
+ P = data & 0xf;
+ X = data >> 4;
+ IE = ie;
+}
+
+void cosmac_device::ret() { return_from_interrupt(1); }
+void cosmac_device::dis() { return_from_interrupt(0); }
+
+// input/output byte transfer opcode handlers
+void cosmac_device::out() { IO_W(N, RAM_R(R[X])); R[X]++; }
+
+/*
+
+ A note about INP 0 (0x68) from Tom Pittman's "A Short Course in Programming":
+
+ If you look carefully, you will notice that we never studied the opcode "68".
+ That's because it is not a defined 1802 instruction. It has the form of an INP
+ instruction, but 0 is not a defined input port, so if you execute it (try it!)
+ nothing is input. "Nothing" is the answer to a question; it is data, and something
+ will be put in the accumulator and memory (so now you know what the computer uses
+ to mean "nothing").
+
+ However, since the result of the "68" opcode is unpredictable, it should not be
+ used in your programs. In fact, "68" is the first byte of a series of additional
+ instructions for the 1804 and 1805 microprocessors.
+
+ http://www.ittybittycomputers.com/IttyBitty/ShortCor.htm
+
+*/
+void cosmac_device::inp() { D = IO_R(N & 0x07); RAM_W(R[X], D); }
diff --git a/src/emu/cpu/cosmac/cosmac.h b/src/emu/cpu/cosmac/cosmac.h
new file mode 100644
index 00000000000..a057f43990e
--- /dev/null
+++ b/src/emu/cpu/cosmac/cosmac.h
@@ -0,0 +1,414 @@
+/**********************************************************************
+
+ RCA "COSMAC" CPU emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ CLOCK 1 |* \_/ | 40 Vdd
+ _WAIT 2 | | 39 _XTAL
+ _CLEAR 3 | | 38 _DMA IN
+ Q 4 | | 37 _DMA OUT
+ SC1 5 | | 36 _INTERRUPT
+ SC0 6 | | 35 _MWR
+ _MRD 7 | | 34 TPA
+ BUS 7 8 | | 33 TPB
+ BUS 6 9 | CDP1802 | 32 MA7
+ BUS 5 10 | CDP1803 | 31 MA6
+ BUS 4 11 | CDP1804 | 30 MA5
+ BUS 3 12 | CDP1805 | 29 MA4
+ BUS 2 13 | CDP1806 | 28 MA3
+ BUS 1 14 | | 27 MA2
+ BUS 0 15 | | 26 MA1
+ * 16 | | 25 MA0
+ N2 17 | | 24 _EF1
+ N1 18 | | 23 _EF2
+ N0 19 | | 22 _EF3
+ Vss 20 |_____________| 21 _EF4
+
+
+ Type Internal ROM Internal RAM Timer Pin 16 (*)
+ ------------------------------------------------------------------
+ CDP1802 none none no Vcc
+ CDP1803 ? ? ? ?
+ CDP1804 2 KB 64 bytes yes ?
+ CDP1805 none 64 bytes yes _ME
+ CDP1806 none none yes Vdd
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __COSMAC_H__
+#define __COSMAC_H__
+
+
+//**************************************************************************
+// ENUMERATIONS
+//**************************************************************************
+
+// registers
+enum
+{
+ COSMAC_P,
+ COSMAC_X,
+ COSMAC_D,
+ COSMAC_B,
+ COSMAC_T,
+ COSMAC_R0,
+ COSMAC_R1,
+ COSMAC_R2,
+ COSMAC_R3,
+ COSMAC_R4,
+ COSMAC_R5,
+ COSMAC_R6,
+ COSMAC_R7,
+ COSMAC_R8,
+ COSMAC_R9,
+ COSMAC_Ra,
+ COSMAC_Rb,
+ COSMAC_Rc,
+ COSMAC_Rd,
+ COSMAC_Re,
+ COSMAC_Rf,
+ COSMAC_DF,
+ COSMAC_IE,
+ COSMAC_Q,
+ COSMAC_N,
+ COSMAC_I,
+ COSMAC_SC
+};
+
+
+// input lines
+enum
+{
+ COSMAC_INPUT_LINE_INT = 0,
+ COSMAC_INPUT_LINE_DMAIN,
+ COSMAC_INPUT_LINE_DMAOUT,
+ COSMAC_INPUT_LINE_EF1,
+ COSMAC_INPUT_LINE_EF2,
+ COSMAC_INPUT_LINE_EF3,
+ COSMAC_INPUT_LINE_EF4,
+};
+
+
+// state codes
+enum cosmac_state_code
+{
+ COSMAC_STATE_CODE_S0_FETCH = 0,
+ COSMAC_STATE_CODE_S1_EXECUTE,
+ COSMAC_STATE_CODE_S2_DMA,
+ COSMAC_STATE_CODE_S3_INTERRUPT
+};
+
+
+// device type definition
+extern const device_type COSMAC;
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+typedef void (*cosmac_out_sc_func)(running_device *device, cosmac_state_code sc);
+#define COSMAC_SC_WRITE(name) void name(running_device *device, cosmac_state_code sc)
+
+
+// ======================> cosmac_interface
+
+struct cosmac_interface
+{
+ devcb_read_line m_in_wait_func;
+ devcb_read_line m_in_clear_func;
+ devcb_read_line m_in_ef1_func;
+ devcb_read_line m_in_ef2_func;
+ devcb_read_line m_in_ef3_func;
+ devcb_read_line m_in_ef4_func;
+ devcb_write_line m_out_q_func;
+ devcb_read8 m_in_dma_func;
+ devcb_write8 m_out_dma_func;
+ cosmac_out_sc_func m_out_sc_func;
+ devcb_write_line m_out_tpa_func;
+ devcb_write_line m_out_tpb_func;
+};
+
+#define COSMAC_INTERFACE(name) \
+ const cosmac_interface (name) =
+
+
+// ======================> cosmac_device_config
+
+class cosmac_device_config : public cpu_device_config,
+ public cosmac_interface
+{
+ friend class cosmac_device;
+
+ // construction/destruction
+ cosmac_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
+
+public:
+ // allocators
+ static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
+ virtual device_t *alloc_device(running_machine &machine) const;
+
+protected:
+ // device_config overrides
+ virtual void device_config_complete();
+
+ // device_config_execute_interface overrides
+ virtual UINT32 execute_min_cycles() const;
+ virtual UINT32 execute_max_cycles() const;
+ virtual UINT32 execute_input_lines() const;
+
+ // device_config_memory_interface overrides
+ virtual const address_space_config *memory_space_config(int spacenum = 0) const;
+
+ // device_config_disasm_interface overrides
+ virtual UINT32 disasm_min_opcode_bytes() const;
+ virtual UINT32 disasm_max_opcode_bytes() const;
+
+ // inline data
+ const address_space_config m_program_config;
+ const address_space_config m_io_config;
+};
+
+
+
+// ======================> cosmac_device
+
+class cosmac_device : public cpu_device
+{
+ friend class cosmac_device_config;
+
+ // construction/destruction
+ cosmac_device(running_machine &_machine, const cosmac_device_config &config);
+
+public:
+ // public interfaces
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_execute_interface overrides
+ virtual void execute_run();
+ virtual void execute_set_input(int inputnum, int state);
+
+ // device_state_interface overrides
+ virtual void state_import(const device_state_entry &entry);
+ virtual void state_export(const device_state_entry &entry);
+ virtual void state_string_export(const device_state_entry &entry, astring &string);
+
+ // device_disasm_interface overrides
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+ // helpers
+ inline UINT8 read_opcode(offs_t pc);
+ inline UINT8 read_byte(offs_t address);
+ inline UINT8 read_io_byte(offs_t address);
+ inline void write_byte(offs_t address, UINT8 data);
+ inline void write_io_byte(offs_t address, UINT8 data);
+
+ // execution logic
+ inline void run();
+ inline void debug();
+ inline void reset();
+ inline void initialize();
+ inline void fetch_instruction();
+ inline void fetch_instruction_debug();
+ inline void execute_instruction();
+ inline void dma_input();
+ inline void dma_output();
+ inline void interrupt();
+ inline void sample_wait_clear();
+ inline void sample_ef_lines();
+ inline void output_state_code();
+ inline void set_q_flag(int state);
+
+ // arithmetic handlers
+ void add(int left, int right);
+ void add_with_carry(int left, int right);
+ void subtract(int left, int right);
+ void subtract_with_borrow(int left, int right);
+
+ // condition handlers
+ void short_branch(int taken);
+ void long_branch(int taken);
+ void long_skip(int taken);
+
+ // control handlers
+ void return_from_interrupt(int ie);
+
+ // memory reference opcode handlers
+ void ldn();
+ void lda();
+ void ldx();
+ void ldxa();
+ void ldi();
+ void str();
+ void stxd();
+
+ // register operations opcode handlers
+ void inc();
+ void dec();
+ void irx();
+ void glo();
+ void plo();
+ void ghi();
+ void phi();
+
+ // logic operations opcode handlers
+ void _or();
+ void ori();
+ void _xor();
+ void xri();
+ void _and();
+ void ani();
+ void shr();
+ void shrc();
+ void shl();
+ void shlc();
+
+ // arithmetic operations opcode handlers
+ void add();
+ void adi();
+ void adc();
+ void adci();
+ void sd();
+ void sdi();
+ void sdb();
+ void sdbi();
+ void sm();
+ void smi();
+ void smb();
+ void smbi();
+
+ // short branch instructions opcode handlers
+ void br();
+ void nbr();
+ void bz();
+ void bnz();
+ void bdf();
+ void bnf();
+ void bq();
+ void bnq();
+ void b();
+ void bn();
+
+ // long branch instructions opcode handlers
+ void lbr();
+ void nlbr();
+ void lbz();
+ void lbnz();
+ void lbdf();
+ void lbnf();
+ void lbq();
+ void lbnq();
+
+ // skip instructions opcode handlers
+ void lsz();
+ void lsnz();
+ void lsdf();
+ void lsnf();
+ void lsq();
+ void lsnq();
+ void lsie();
+
+ // control instructions opcode handlers
+ void idl();
+ void nop();
+ void sep();
+ void sex();
+ void seq();
+ void req();
+ void sav();
+ void mark();
+ void ret();
+ void dis();
+
+ // input/output byte transfer opcode handlers
+ void out();
+ void inp();
+
+ // device callbacks
+ devcb_resolved_read_line m_in_wait_func;
+ devcb_resolved_read_line m_in_clear_func;
+ devcb_resolved_read_line m_in_ef_func[4];
+ devcb_resolved_write_line m_out_q_func;
+ devcb_resolved_read8 m_in_dma_func;
+ devcb_resolved_write8 m_out_dma_func;
+ cosmac_out_sc_func m_out_sc_func;
+ devcb_resolved_write_line m_out_tpa_func;
+ devcb_resolved_write_line m_out_tpb_func;
+
+ // control modes
+ enum _cosmac_mode
+ {
+ COSMAC_MODE_LOAD = 0,
+ COSMAC_MODE_RESET,
+ COSMAC_MODE_PAUSE,
+ COSMAC_MODE_RUN
+ };
+ typedef enum _cosmac_mode cosmac_mode;
+
+ // execution states
+ enum _cosmac_state
+ {
+ COSMAC_STATE_0_FETCH = 0,
+ COSMAC_STATE_1_RESET,
+ COSMAC_STATE_1_INIT,
+ COSMAC_STATE_1_EXECUTE,
+ COSMAC_STATE_2_DMA_IN,
+ COSMAC_STATE_2_DMA_OUT,
+ COSMAC_STATE_3_INT
+ };
+ typedef enum _cosmac_state cosmac_state;
+
+ // internal state
+ UINT8 m_op; // current opcode
+ UINT8 m_flagsio; // flags storage for state saving
+ cosmac_state m_state; // state
+ cosmac_mode m_mode; // control mode
+ cosmac_mode m_pmode; // previous control mode
+ int m_irq; // interrupt request
+ int m_dmain; // DMA input request
+ int m_dmaout; // DMA output request
+ int m_ef[4]; // external flags
+
+ // registers
+ UINT8 m_d; // data register (accumulator)
+ UINT8 m_b; // auxiliary holding register
+ UINT16 m_r[16]; // scratchpad registers
+ UINT8 m_p; // designates which register is Program Counter
+ UINT8 m_x; // designates which register is Data Pointer
+ UINT8 m_n; // low-order instruction digit
+ UINT8 m_i; // high-order instruction digit
+ UINT8 m_t; // temporary register
+
+ // flags
+ int m_df; // data flag (ALU carry)
+ int m_ie; // interrupt enable
+ int m_q; // output flip-flop
+
+ // internal stuff
+ int m_icount;
+ address_space * m_program;
+ address_space * m_io;
+ direct_read_data * m_direct;
+
+ // opcode/condition tables
+ typedef void (cosmac_device::*ophandler)();
+
+ static const ophandler s_opcodetable[256];
+
+ const cosmac_device_config &m_config;
+};
+
+
+
+#endif /* __COSMAC_H__ */
diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak
index 984197051bc..123961fc99b 100644
--- a/src/emu/cpu/cpu.mak
+++ b/src/emu/cpu/cpu.mak
@@ -291,6 +291,21 @@ $(CPUOBJ)/cdp1802/cdp1802.o: $(CPUSRC)/cdp1802/cdp1802.c \
#-------------------------------------------------
+# RCA COSMAC
+#-------------------------------------------------
+
+ifneq ($(filter COSMAC,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/cosmac
+CPUOBJS += $(CPUOBJ)/cosmac/cosmac.o
+DASMOBJS += $(CPUOBJ)/cosmac/cosdasm.o
+endif
+
+$(CPUOBJ)/cosmac/cosmac.o: $(CPUSRC)/cosmac/cosmac.c \
+ $(CPUSRC)/cosmac/cosmac.h
+
+
+
+#-------------------------------------------------
# National Semiconductor COP400 family
#-------------------------------------------------
diff --git a/src/emu/sound/cdp1869.c b/src/emu/sound/cdp1869.c
index ae2a95682a8..21108cf0576 100644
--- a/src/emu/sound/cdp1869.c
+++ b/src/emu/sound/cdp1869.c
@@ -1,6 +1,6 @@
#include "emu.h"
#include "streams.h"
-#include "cpu/cdp1802/cdp1802.h"
+#include "cpu/cosmac/cosmac.h"
#include "sound/cdp1869.h"
/*
@@ -135,22 +135,22 @@ static void update_prd_changed_timer(cdp1869_t *cdp1869)
if (scanline < start)
{
next_scanline = start;
- level = 0;
+ level = ASSERT_LINE;
}
else if (scanline < end)
{
next_scanline = end;
- level = 1;
+ level = CLEAR_LINE;
}
else
{
next_scanline = start;
- level = 0;
+ level = ASSERT_LINE;
}
if (cdp1869->dispoff)
{
- level = 1;
+ level = CLEAR_LINE;
}
duration = cdp1869->screen->time_until_pos(next_scanline);
@@ -188,7 +188,7 @@ static STATE_POSTLOAD( cdp1869_state_save_postload )
static UINT16 cdp1802_get_r_x(cdp1869_t *cdp1869)
{
- return cpu_get_reg(cdp1869->cpu, CDP1802_R0 + cpu_get_reg(cdp1869->cpu, CDP1802_X));
+ return cpu_get_reg(cdp1869->cpu, COSMAC_R0 + cpu_get_reg(cdp1869->cpu, COSMAC_X));
}
/*-------------------------------------------------
@@ -713,6 +713,17 @@ READ_LINE_DEVICE_HANDLER( cdp1869_predisplay_r )
}
/*-------------------------------------------------
+ cdp1869_pal_ntsc_r - PAL/NTSC read
+-------------------------------------------------*/
+
+READ_LINE_DEVICE_HANDLER( cdp1869_pal_ntsc_r )
+{
+ cdp1869_t *cdp1869 = get_safe_token(device);
+
+ return devcb_call_read_line(&cdp1869->in_pal_ntsc_func);
+}
+
+/*-------------------------------------------------
cdp1869_update - screen update
-------------------------------------------------*/
diff --git a/src/emu/sound/cdp1869.h b/src/emu/sound/cdp1869.h
index afcfb6e59d9..1f4d05c3a55 100644
--- a/src/emu/sound/cdp1869.h
+++ b/src/emu/sound/cdp1869.h
@@ -183,6 +183,9 @@ WRITE8_DEVICE_HANDLER ( cdp1869_pageram_w );
/* predisplay */
READ_LINE_DEVICE_HANDLER( cdp1869_predisplay_r );
+/* PAL/NTSC */
+READ_LINE_DEVICE_HANDLER( cdp1869_pal_ntsc_r );
+
/* screen update */
void cdp1869_update(running_device *device, bitmap_t *bitmap, const rectangle *cliprect);
diff --git a/src/mame/drivers/cidelsa.c b/src/mame/drivers/cidelsa.c
index 7290711e9be..973faa0240e 100644
--- a/src/mame/drivers/cidelsa.c
+++ b/src/mame/drivers/cidelsa.c
@@ -1,5 +1,5 @@
#include "emu.h"
-#include "cpu/cdp1802/cdp1802.h"
+#include "cpu/cosmac/cosmac.h"
#include "cpu/cop400/cop400.h"
#include "sound/cdp1869.h"
#include "sound/ay8910.h"
@@ -9,23 +9,11 @@
/* CDP1802 Interface */
-static CDP1802_MODE_READ( cidelsa_mode_r )
+static READ_LINE_DEVICE_HANDLER( clear_r )
{
cidelsa_state *state = device->machine->driver_data<cidelsa_state>();
- return state->cdp1802_mode;
-}
-
-static CDP1802_EF_READ( cidelsa_ef_r )
-{
- /*
- EF1 CDP1869 _PRD
- EF2 Test
- EF3 Coin 2
- EF4 Coin 1
- */
-
- return input_port_read(device->machine, "EF");
+ return state->reset;
}
static WRITE_LINE_DEVICE_HANDLER( cidelsa_q_w )
@@ -35,14 +23,20 @@ static WRITE_LINE_DEVICE_HANDLER( cidelsa_q_w )
driver_state->cdp1802_q = state;
}
-static CDP1802_INTERFACE( cidelsa_cdp1802_config )
+static COSMAC_INTERFACE( cidelsa_cdp1802_config )
{
- cidelsa_mode_r, // MODE
- cidelsa_ef_r, // EF
- NULL, // SC
- DEVCB_LINE(cidelsa_q_w), // Q
- DEVCB_NULL, // DMA read
- DEVCB_NULL // DMA write
+ DEVCB_LINE_VCC,
+ DEVCB_LINE(clear_r),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_LINE(cidelsa_q_w),
+ DEVCB_NULL,
+ DEVCB_NULL,
+ NULL,
+ DEVCB_NULL,
+ DEVCB_NULL
};
/* Sound Interface */
@@ -258,7 +252,7 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( altair_map, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x2fff) AM_ROM
- AM_RANGE(0x3000, 0x30ff) AM_RAM
+ AM_RANGE(0x3000, 0x30ff) AM_RAM AM_SHARE("nvram")
AM_RANGE(0xf400, 0xf7ff) AM_DEVREADWRITE(CDP1869_TAG, cdp1869_charram_r, cdp1869_charram_w)
AM_RANGE(0xf800, 0xffff) AM_DEVREADWRITE(CDP1869_TAG, cdp1869_pageram_r, cdp1869_pageram_w)
ADDRESS_MAP_END
@@ -314,11 +308,9 @@ static CUSTOM_INPUT( cdp1869_pcb_r )
return state->cdp1869_pcb;
}
-static CUSTOM_INPUT( cidelsa_prd_r )
+static INPUT_CHANGED( ef_w )
{
- cidelsa_state *state = field->port->machine->driver_data<cidelsa_state>();
-
- return state->cdp1869_prd;
+ cputag_set_input_line(field->port->machine, CDP1802_TAG, (int)(FPTR)param, newval);
}
static INPUT_PORTS_START( destryer )
@@ -355,10 +347,10 @@ static INPUT_PORTS_START( destryer )
PORT_DIPSETTING( 0x00, "Slot A: 2.5 Slot B: 5" )
PORT_START("EF")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM(cidelsa_prd_r, NULL)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SERVICE ) // ST
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN2 ) // M2
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN1 ) // M1
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_SPECIAL ) // inverted CDP1869 PRD, pushed
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SERVICE ) PORT_CHANGED(ef_w, (void*)COSMAC_INPUT_LINE_EF2)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_CHANGED(ef_w, (void*)COSMAC_INPUT_LINE_EF3)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED(ef_w, (void*)COSMAC_INPUT_LINE_EF4)
INPUT_PORTS_END
static INPUT_PORTS_START( altair )
@@ -405,10 +397,10 @@ static INPUT_PORTS_START( altair )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("EF")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM(cidelsa_prd_r, NULL)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SERVICE ) // ST
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN2 ) // M2
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN1 ) // M1
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_SPECIAL ) // inverted CDP1869 PRD, pushed
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SERVICE ) PORT_CHANGED(ef_w, (void*)COSMAC_INPUT_LINE_EF2)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_CHANGED(ef_w, (void*)COSMAC_INPUT_LINE_EF3)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED(ef_w, (void*)COSMAC_INPUT_LINE_EF4)
INPUT_PORTS_END
static INPUT_PORTS_START( draco )
@@ -457,10 +449,10 @@ static INPUT_PORTS_START( draco )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT )
PORT_START("EF")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_READ_LINE_DEVICE(CDP1869_TAG, cdp1869_predisplay_r)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SERVICE ) // ST
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN2 ) // M2
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN1 ) // M1
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_SPECIAL ) // CDP1869 PRD, pushed
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SERVICE ) PORT_CHANGED(ef_w, (void*)COSMAC_INPUT_LINE_EF2)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_CHANGED(ef_w, (void*)COSMAC_INPUT_LINE_EF3)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED(ef_w, (void*)COSMAC_INPUT_LINE_EF4)
INPUT_PORTS_END
/* Machine Start */
@@ -469,21 +461,18 @@ static TIMER_CALLBACK( set_cpu_mode )
{
cidelsa_state *state = machine->driver_data<cidelsa_state>();
- state->cdp1802_mode = CDP1802_MODE_RUN;
+ state->reset = 1;
}
static MACHINE_START( cidelsa )
{
cidelsa_state *state = machine->driver_data<cidelsa_state>();
+ /* find devices */
state->cdp1802 = machine->device(CDP1802_TAG);
- /* reset the CPU */
- state->cdp1802_mode = CDP1802_MODE_RESET;
- timer_set(machine, ATTOTIME_IN_MSEC(200), NULL, 0, set_cpu_mode);
-
/* register for state saving */
- state_save_register_global(machine, state->cdp1802_mode);
+ state_save_register_global(machine, state->reset);
}
static MACHINE_START( draco )
@@ -493,7 +482,7 @@ static MACHINE_START( draco )
MACHINE_START_CALL( cidelsa );
/* setup COP402 memory banking */
- memory_configure_bank(machine, "bank1", 0, 2, memory_region(machine, "audiocpu"), 0x400);
+ memory_configure_bank(machine, "bank1", 0, 2, memory_region(machine, COP402N_TAG), 0x400);
memory_set_bank(machine, "bank1", 0);
/* register for state saving */
@@ -505,15 +494,18 @@ static MACHINE_START( draco )
static MACHINE_RESET( cidelsa )
{
- cputag_set_input_line(machine, CDP1802_TAG, INPUT_LINE_RESET, PULSE_LINE);
+ cidelsa_state *state = machine->driver_data<cidelsa_state>();
+
+ /* reset the CPU */
+ state->reset = 0;
+ timer_set(machine, ATTOTIME_IN_MSEC(200), NULL, 0, set_cpu_mode);
}
/* Machine Drivers */
static MACHINE_CONFIG_START( destryer, cidelsa_state )
-
/* basic system hardware */
- MDRV_CPU_ADD(CDP1802_TAG, CDP1802, DESTRYER_CHR1)
+ MDRV_CPU_ADD(CDP1802_TAG, COSMAC, DESTRYER_CHR1)
MDRV_CPU_PROGRAM_MAP(destryer_map)
MDRV_CPU_IO_MAP(destryer_io_map)
MDRV_CPU_CONFIG(cidelsa_cdp1802_config)
@@ -527,9 +519,8 @@ static MACHINE_CONFIG_START( destryer, cidelsa_state )
MACHINE_CONFIG_END
static MACHINE_CONFIG_START( destryera, cidelsa_state )
-
/* basic system hardware */
- MDRV_CPU_ADD(CDP1802_TAG, CDP1802, DESTRYER_CHR1)
+ MDRV_CPU_ADD(CDP1802_TAG, COSMAC, DESTRYER_CHR1)
MDRV_CPU_PROGRAM_MAP(destryera_map)
MDRV_CPU_IO_MAP(destryer_io_map)
MDRV_CPU_CONFIG(cidelsa_cdp1802_config)
@@ -543,13 +534,12 @@ static MACHINE_CONFIG_START( destryera, cidelsa_state )
MACHINE_CONFIG_END
static MACHINE_CONFIG_START( altair, cidelsa_state )
-
/* basic system hardware */
-
- MDRV_CPU_ADD(CDP1802_TAG, CDP1802, ALTAIR_CHR1)
+ MDRV_CPU_ADD(CDP1802_TAG, COSMAC, ALTAIR_CHR1)
MDRV_CPU_PROGRAM_MAP(altair_map)
MDRV_CPU_IO_MAP(altair_io_map)
MDRV_CPU_CONFIG(cidelsa_cdp1802_config)
+ MDRV_NVRAM_ADD_0FILL("nvram")
MDRV_MACHINE_START(cidelsa)
MDRV_MACHINE_RESET(cidelsa)
@@ -565,9 +555,8 @@ static MACHINE_CONFIG_START( altair, cidelsa_state )
MACHINE_CONFIG_END
static MACHINE_CONFIG_START( draco, cidelsa_state )
-
/* basic system hardware */
- MDRV_CPU_ADD(CDP1802_TAG, CDP1802, DRACO_CHR1)
+ MDRV_CPU_ADD(CDP1802_TAG, COSMAC, DRACO_CHR1)
MDRV_CPU_PROGRAM_MAP(draco_map)
MDRV_CPU_IO_MAP(draco_io_map)
MDRV_CPU_CONFIG(cidelsa_cdp1802_config)
@@ -576,7 +565,7 @@ static MACHINE_CONFIG_START( draco, cidelsa_state )
MDRV_MACHINE_START(draco)
MDRV_MACHINE_RESET(cidelsa)
- MDRV_CPU_ADD("audiocpu", COP402, DRACO_SND_CHR1) // COP402N
+ MDRV_CPU_ADD(COP402N_TAG, COP402, DRACO_SND_CHR1)
MDRV_CPU_PROGRAM_MAP(draco_sound_map)
MDRV_CPU_IO_MAP(draco_sound_io_map)
MDRV_CPU_CONFIG(draco_cop_intf)
@@ -594,7 +583,7 @@ MACHINE_CONFIG_END
/* ROMs */
ROM_START( destryer )
- ROM_REGION( 0x10000, CDP1802_TAG, 0 )
+ ROM_REGION( 0x2000, CDP1802_TAG, 0 )
ROM_LOAD( "des a 2.ic4", 0x0000, 0x0800, CRC(63749870) SHA1(a8eee4509d7a52dcf33049de221d928da3632174) )
ROM_LOAD( "des b 2.ic5", 0x0800, 0x0800, CRC(60604f40) SHA1(32ca95c5b38b0f4992e04d77123d217f143ae084) )
ROM_LOAD( "des c 2.ic6", 0x1000, 0x0800, CRC(a7cdeb7b) SHA1(a5a7748967d4ca89fb09632e1f0130ef050dbd68) )
@@ -603,7 +592,7 @@ ROM_END
// this was destroyer2.rom in standalone emu..
ROM_START( destryera )
- ROM_REGION( 0x10000, CDP1802_TAG, 0 )
+ ROM_REGION( 0x2000, CDP1802_TAG, 0 )
ROM_LOAD( "destryera_1", 0x0000, 0x0800, CRC(421428e9) SHA1(0ac3a1e7f61125a1cd82145fa28cbc4b93505dc9) )
ROM_LOAD( "destryera_2", 0x0800, 0x0800, CRC(55dc8145) SHA1(a0066d3f3ac0ae56273485b74af90eeffea5e64e) )
ROM_LOAD( "destryera_3", 0x1000, 0x0800, CRC(5557bdf8) SHA1(37a9cbc5d25051d3bed7535c58aac937cd7c64e1) )
@@ -611,7 +600,7 @@ ROM_START( destryera )
ROM_END
ROM_START( altair )
- ROM_REGION( 0x10000, CDP1802_TAG, 0 )
+ ROM_REGION( 0x3000, CDP1802_TAG, 0 )
ROM_LOAD( "alt a 1.ic7", 0x0000, 0x0800, CRC(37c26c4e) SHA1(30df7efcf5bd12dafc1cb6e894fc18e7b76d3e61) )
ROM_LOAD( "alt b 1.ic8", 0x0800, 0x0800, CRC(76b814a4) SHA1(e8ab1d1cbcef974d929ef8edd10008f60052a607) )
ROM_LOAD( "alt c 1.ic9", 0x1000, 0x0800, CRC(2569ce44) SHA1(a09597d2f8f50fab9a09ed9a59c50a2bdcba47bb) )
@@ -621,7 +610,7 @@ ROM_START( altair )
ROM_END
ROM_START( draco )
- ROM_REGION( 0x10000, CDP1802_TAG, 0 )
+ ROM_REGION( 0x4000, CDP1802_TAG, 0 )
ROM_LOAD( "dra a 1.ic10", 0x0000, 0x0800, CRC(ca127984) SHA1(46721cf42b1c891f7c88bc063a2149dd3cefea74) )
ROM_LOAD( "dra b 1.ic11", 0x0800, 0x0800, CRC(e4936e28) SHA1(ddbbf769994d32a6bce75312306468a89033f0aa) )
ROM_LOAD( "dra c 1.ic12", 0x1000, 0x0800, CRC(94480f5d) SHA1(8f49ce0f086259371e999d097a502482c83c6e9e) )
@@ -631,7 +620,7 @@ ROM_START( draco )
ROM_LOAD( "dra g 1.ic16", 0x3000, 0x0800, CRC(f28546c0) SHA1(daedf1d64f94358b15580d697dd77d3c977aa22c) )
ROM_LOAD( "dra h 1.ic17", 0x3800, 0x0800, CRC(dce782ea) SHA1(f558096f43fb30337bc4a527169718326c265c2c) )
- ROM_REGION( 0x800, "audiocpu", 0 )
+ ROM_REGION( 0x800, COP402N_TAG, 0 )
ROM_LOAD( "dra s 1.ic4", 0x0000, 0x0800, CRC(292a57f8) SHA1(b34a189394746d77c3ee669db24109ee945c3be7) )
ROM_END
diff --git a/src/mame/includes/cidelsa.h b/src/mame/includes/cidelsa.h
index 1d77186a51a..beec3c32954 100644
--- a/src/mame/includes/cidelsa.h
+++ b/src/mame/includes/cidelsa.h
@@ -1,11 +1,12 @@
#ifndef __CIDELSA__
#define __CIDELSA__
-#include "cpu/cdp1802/cdp1802.h"
+#include "cpu/cosmac/cosmac.h"
#define SCREEN_TAG "screen"
#define CDP1802_TAG "cdp1802"
#define CDP1869_TAG "cdp1869"
+#define COP402N_TAG "cop402n"
#define AY8910_TAG "ay8910"
#define DESTRYER_CHR1 3579000.0 // unverified
@@ -31,7 +32,7 @@ public:
: driver_device(machine, config) { }
/* cpu state */
- cdp1802_control_mode cdp1802_mode;
+ int reset;
/* video state */
int cdp1802_q;
diff --git a/src/mame/mame.mak b/src/mame/mame.mak
index bf691e3d6d1..7694ea1b1ca 100644
--- a/src/mame/mame.mak
+++ b/src/mame/mame.mak
@@ -122,6 +122,7 @@ CPUS += Z8
CPUS += I8008
CPUS += SCMP
CPUS += MN10200
+CPUS += COSMAC
#-------------------------------------------------
# specify available sound cores; some of these are
diff --git a/src/mame/video/cidelsa.c b/src/mame/video/cidelsa.c
index 7e4de9dc637..be53c53e9d4 100644
--- a/src/mame/video/cidelsa.c
+++ b/src/mame/video/cidelsa.c
@@ -1,4 +1,5 @@
#include "emu.h"
+#include "cpu/cosmac/cosmac.h"
#include "sound/cdp1869.h"
#include "sound/ay8910.h"
#include "includes/cidelsa.h"
@@ -130,8 +131,8 @@ static WRITE_LINE_DEVICE_HANDLER( cidelsa_prd_w )
cidelsa_state *driver_state = device->machine->driver_data<cidelsa_state>();
/* invert PRD signal */
- cpu_set_input_line(driver_state->cdp1802, INPUT_LINE_IRQ0, !state);
- driver_state->cdp1869_prd = !state;
+ cpu_set_input_line(driver_state->cdp1802, COSMAC_INPUT_LINE_INT, state ? CLEAR_LINE : ASSERT_LINE);
+ cpu_set_input_line(driver_state->cdp1802, COSMAC_INPUT_LINE_EF1, state ? CLEAR_LINE : ASSERT_LINE);
}
/* CDP1869 Interface */
@@ -175,7 +176,7 @@ static CDP1869_INTERFACE( draco_cdp1869_intf )
draco_pcb_r,
draco_charram_r,
draco_charram_w,
- DEVCB_NULL
+ DEVCB_CPU_INPUT_LINE(CDP1802_TAG, COSMAC_INPUT_LINE_EF1)
};
/* Video Start */