vsmile: Fixed erroneous cartridge ROM mirroring. Gets V.Smile games to boot. Needs cleanup. [Ryan Holtz]

This commit is contained in:
mooglyguy 2018-10-21 21:11:09 +02:00
parent 5e85036f34
commit af515310d7
7 changed files with 1383 additions and 922 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,14 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
// license:GPL-2.0+
// copyright-holders:Segher Boessenkool,Ryan Holtz
/*****************************************************************************
SunPlus micro'nSP core
SunPlus micro'nSP emulator
based primarily on Unununium, by segher
Copyright 2008-2017 Segher Boessenkool <segher@kernel.crashing.org>
Licensed under the terms of the GNU GPL, version 2
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
Ported to MAME framework by Ryan Holtz
*****************************************************************************/
@ -13,7 +17,7 @@
#pragma once
#define UNSP_LOG_OPCODES (0)
#define UNSP_LOG_OPCODES (1)
enum
{
@ -56,6 +60,13 @@ enum
UNSP_NUM_LINES
};
struct unsp_timer
{
uint32_t time;
uint32_t interval;
int index;
struct unsp_timer *next;
};
class unsp_device : public cpu_device
{
@ -63,6 +74,10 @@ public:
// construction/destruction
unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void set_timer_interval(int timer, uint32_t interval);
uint16_t get_video_line();
protected:
// device-level overrides
virtual void device_start() override;
@ -87,8 +102,15 @@ protected:
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
private:
void add_lpc(const int32_t offset);
inline void execute_one(const uint16_t op);
address_space_config m_program_config;
void timer_add(struct unsp_timer *timer);
void timer_run(uint32_t ticks);
uint16_t m_r[16];
bool m_enable_irq;
bool m_enable_fiq;
@ -98,6 +120,7 @@ private:
uint16_t m_sirq;
uint8_t m_sb;
uint8_t m_saved_sb[3];
struct unsp_timer *timers;
address_space *m_program;
int m_icount;
@ -117,6 +140,7 @@ private:
inline void trigger_fiq();
inline void trigger_irq(int line);
inline void check_irqs();
inline int get_irq();
};

View File

@ -1,257 +1,435 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
// license:GPL-2.0+
// copyright-holders:Segher Boessenkool
/*****************************************************************************
SunPlus micro'nSP disassembler
Copyright 2008-2017 Segher Boessenkool <segher@kernel.crashing.org>
Licensed under the terms of the GNU GPL, version 2
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
*****************************************************************************/
#include "emu.h"
#include "unspdasm.h"
char const *const unsp_disassembler::reg[] =
char const *const unsp_disassembler::regs[] =
{
"sp", "r1", "r2", "r3", "r4", "bp", "sr", "pc"
};
char const *const unsp_disassembler::jmp[] =
char const *const unsp_disassembler::jumps[] =
{
"jb", "jae", "jge", "jl", "jne", "je", "jpl", "jmi",
"jbe", "ja", "jle", "jg", "jvc", "jvs", "jmp", "<inv>"
};
char const *const unsp_disassembler::alu[] =
{
"add", "adc", "sub", "sbc",
"cmp", "<inv>", "neg", "<inv>",
"xor", "load", "or", "and",
"test", "store", "<inv>", "<inv>"
};
/*****************************************************************************/
#define OP0 (op >> 12)
#define OPA ((op >> 9) & 7)
#define OP1 ((op >> 6) & 7)
#define OPN ((op >> 3) & 7)
#define OPB (op & 7)
#define OPIMM (op & 0x3f)
#define OP2X ((OP0 < 14 && OP1 == 4 && (OPN >= 1 && OPN <= 3)) || (OP0 == 15 && (OP1 == 1 || OP1 == 2)))
/*****************************************************************************/
#define UNSP_DASM_OK ((OP2X ? 2 : 1) | SUPPORTED)
#define UNSP_DASM_OK (len | SUPPORTED)
u32 unsp_disassembler::opcode_alignment() const
{
return 1;
}
offs_t unsp_disassembler::disassemble(std::ostream &stream, offs_t pc, uint16_t op, uint16_t imm16)
void unsp_disassembler::print_alu_op_start(std::ostream &stream, uint8_t op0, uint8_t opA)
{
if(OP0 < 0xf && OPA == 0x7 && OP1 < 2)
static const char* const alu_op_start[] =
{
util::stream_format(stream, "%s %04x", jmp[OP0], OP1 ? (pc - OPIMM + 1) : (pc + OPIMM + 1));
"%s += ", "%s += ", "%s -= ", "%s -= ",
"cmp %s, ", "<BAD>", "%s =- ", "<BAD>",
"%s ^= ", "%s = ", "%s |= ", "%s &= ",
"test %s, "
};
util::stream_format(stream, alu_op_start[op0], regs[opA]);
}
void unsp_disassembler::print_alu_op3(std::ostream &stream, uint8_t op0, uint8_t opB)
{
static const char* const alu_op3[] =
{
"%s + ", "%s + ", "%s - ", "%s - ",
"cmp %s, ", "<BAD>", "-", "<BAD>",
"%s ^ ", "", "%s | ", "%s & ",
"test %s, "
};
util::stream_format(stream, alu_op3[op0], regs[opB]);
}
void unsp_disassembler::print_alu_op_end(std::ostream &stream, uint8_t op0)
{
if (op0 == 1 || op0 == 3)
util::stream_format(stream, ", carry");
}
void unsp_disassembler::print_indirect_op(std::ostream &stream, uint8_t opN, uint8_t opB)
{
static const char* const forms[] = { "[%s]", "[%s--]", "[%s++]", "[++%s]" };
if (opN & 4)
util::stream_format(stream, "ds:");
util::stream_format(stream, forms[opN & 3], regs[opB]);
}
offs_t unsp_disassembler::disassemble(std::ostream &stream, offs_t pc, uint16_t op, uint16_t ximm)
{
// the top four bits are the alu op or the branch condition, or E or F
uint8_t op0 = (op >> 12);
// the next three are usually the destination register
uint8_t opA = (op >> 9) & 7;
// and the next three the addressing mode
uint8_t op1 = (op >> 6) & 7;
// the next three can be anything
uint8_t opN = (op >> 3) & 7;
// and the last three usually the second register (source register)
uint8_t opB = op & 7;
// the last six sometimes are a single immediate number
uint8_t opimm = op & 63;
uint32_t len = 1;
if ((op0 < 14 && op1 == 4 && (opN == 1 || opN == 2 || opN == 3)) || (op0 == 15 && (op1 == 1 || op1 == 2)))
{
len = 2;
}
// all-zero and all-one are invalid insns:
if (op == 0 || op == 0xffff)
{
util::stream_format(stream, "--");
return UNSP_DASM_OK;
}
switch((OP1 << 4) | OP0)
// first, check for the conditional branch insns
if (op0 < 15 && opA == 7 && op1 == 0)
{
// ALU, Indexed
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x06: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d:
util::stream_format(stream, "%s %s, [bp+%02x]", alu[OP0], reg[OPA], OPIMM);
return UNSP_DASM_OK;
// ALU, Immediate
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x16: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c:
util::stream_format(stream, "%s %s, %02x", alu[OP0], reg[OPA], OPIMM);
return UNSP_DASM_OK;
// Pop / Interrupt return
case 0x29:
if(op == 0x9a90)
{
util::stream_format(stream, "retf");
return UNSP_DASM_OK;
}
else if(op == 0x9a98)
{
util::stream_format(stream, "reti");
return UNSP_DASM_OK;
}
else if((OPA + 1) < 8 && ((OPA + OPN) < 8))
{
util::stream_format(stream, "pop %s, %s [%s]", reg[OPA+1], reg[OPA+OPN], reg[OPB]);
return UNSP_DASM_OK;
}
break;
// Push
case 0x2d:
if((OPA + 1) >= OPN && OPA < (OPN + 7))
{
util::stream_format(stream, "push %s, %s [%s]", reg[(OPA+1)-OPN], reg[OPA], reg[OPB]);
return UNSP_DASM_OK;
}
break;
// ALU, Indirect
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x36: case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d:
switch(OPN & 3)
{
case 0:
util::stream_format(stream, "%s %s, [%s%s]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]);
return UNSP_DASM_OK;
case 1:
util::stream_format(stream, "%s %s, [%s%s--]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]);
return UNSP_DASM_OK;
case 2:
util::stream_format(stream, "%s %s, [%s%s++]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]);
return UNSP_DASM_OK;
case 3:
util::stream_format(stream, "%s %s, [%s++%s]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]);
return UNSP_DASM_OK;
}
return UNSP_DASM_OK;
// ALU, 16-bit ops
case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x46: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c:
switch(OPN)
{
// ALU, Register
case 0:
util::stream_format(stream, "%s %s, %s", alu[OP0], reg[OPA], reg[OPB]);
return UNSP_DASM_OK;
// ALU, 16-bit Immediate
case 1:
if(!((OP0 == 4 || OP0 == 6 || OP0 == 9 || OP0 == 12) && OPA != OPB))
{
if(OP0 != 4 && OP0 != 12)
{
util::stream_format(stream, "%s %s, %s, %04x", alu[OP0], reg[OPA], reg[OPB], imm16);
return UNSP_DASM_OK;
}
else
{
util::stream_format(stream, "%s %s, %04x", alu[OP0], reg[OPB], imm16);
return UNSP_DASM_OK;
}
}
break;
// ALU, Direct 16
case 2:
util::stream_format(stream, "%s %s, [%04x]", alu[OP0], reg[OPA], imm16);
return UNSP_DASM_OK;
// ALU, Direct 16
case 3:
util::stream_format(stream, "%s [%04x], %s, %s", alu[OP0], imm16, reg[OPA], reg[OPB]);
return UNSP_DASM_OK;
// ALU, Shifted
default:
util::stream_format(stream, "%s %s, %s asr %d", alu[OP0], reg[OPA], reg[OPB], (OPN & 3) + 1);
return UNSP_DASM_OK;
}
case 0x4d:
if((OPN == 3) && (OPA == OPB))
util::stream_format(stream, "store [%04x], %s", imm16, reg[OPB]);
else
util::stream_format(stream, "<inv>");
return UNSP_DASM_OK;
// ALU, Shifted
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x56: case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c:
util::stream_format(stream, "%s %s, %s %s %d", alu[OP0], reg[OPA], reg[OPB], (OPN & 4) ? ">>" : "<<", (OPN & 3) + 1);
return UNSP_DASM_OK;
// ALU, Rotated
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x66: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c:
util::stream_format(stream, "%s %s, %s %s %d", alu[OP0], reg[OPA], reg[OPB], (OPN & 4) ? "ror" : "rol", (OPN & 3) + 1);
return UNSP_DASM_OK;
// ALU, Direct 8
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x76: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c:
util::stream_format(stream, "%s %s, [%02x]", alu[OP0], reg[OPA], OPIMM);
return UNSP_DASM_OK;
// Call
case 0x1f:
if(OPA == 0)
util::stream_format(stream, "call %06x", (OPIMM << 16) | imm16);
else
util::stream_format(stream, "<inv>");
return UNSP_DASM_OK;
// Far Jump
case 0x2f: case 0x3f: case 0x6f: case 0x7f:
if (OPA == 7 && OP1 == 2)
util::stream_format(stream, "goto %06x", (OPIMM << 16) | imm16);
else
util::stream_format(stream, "<inv>");
return UNSP_DASM_OK;
// Multiply, Unsigned * Signed
case 0x0f:
if(OPN == 1 && OPA != 7)
util::stream_format(stream, "mulus %s, %s", reg[OPA], reg[OPB]);
else
util::stream_format(stream, "<inv>");
return UNSP_DASM_OK;
// Multiply, Signed * Signed
case 0x4f:
if(OPN == 1 && OPA != 7)
util::stream_format(stream, "mulss %s, %s", reg[OPA], reg[OPB]);
else
util::stream_format(stream, "<inv>");
return UNSP_DASM_OK;
// Interrupt flags
case 0x5f:
if(OPA == 0)
{
switch(OPIMM)
{
case 0:
util::stream_format(stream, "int off");
break;
case 1:
util::stream_format(stream, "int irq");
break;
case 2:
util::stream_format(stream, "int fiq");
break;
case 3:
util::stream_format(stream, "int irq,fiq");
break;
case 8:
util::stream_format(stream, "irq off");
break;
case 9:
util::stream_format(stream, "irq on");
break;
case 12:
util::stream_format(stream, "fiq off");
break;
case 14:
util::stream_format(stream, "fiq on");
break;
case 37:
util::stream_format(stream, "nop");
break;
default:
util::stream_format(stream, "<inv>");
break;
}
}
else
util::stream_format(stream, "<inv>");
return UNSP_DASM_OK;
util::stream_format(stream, "%s %04x", jumps[op0], pc+1+opimm);
return UNSP_DASM_OK;
}
if (op0 < 15 && opA == 7 && op1 == 1)
{
util::stream_format(stream, "%s %04x", jumps[op0], pc+1-opimm);
return UNSP_DASM_OK;
}
switch ((op1 << 4) | op0)
{
case 0x05: case 0x15: case 0x25: case 0x35:
case 0x45: case 0x55: case 0x65: case 0x75:
case 0x85: case 0x95: case 0xa5: case 0xb5:
case 0xc5: case 0xd5:
case 0x07: case 0x17: case 0x27: case 0x37:
case 0x47: case 0x57: case 0x67: case 0x77:
case 0x87: case 0x97: case 0xa7: case 0xb7:
case 0xc7: case 0xd7:
case 0x1d: case 0x5d: case 0x6d:
case 0x20: case 0x21: case 0x22: case 0x23:
case 0x24: case 0x26: case 0x28: case 0x2a:
case 0x2b: case 0x2c:
util::stream_format(stream, "<BAD>");
return UNSP_DASM_OK;
// alu, base+displacement
case 0x00: case 0x01: case 0x02: case 0x03:
case 0x04: case 0x06: case 0x08: case 0x09:
case 0x0a: case 0x0b: case 0x0c:
print_alu_op_start(stream, op0, opA);
util::stream_format(stream, "[bp+%02x]", opimm);
print_alu_op_end(stream, op0);
return UNSP_DASM_OK;
case 0x0d:
util::stream_format(stream, "[bp+%02x] = %s", opimm, regs[opA]);
return UNSP_DASM_OK;
// alu, 6-bit immediate
case 0x10: case 0x11: case 0x12: case 0x13:
case 0x14: case 0x16: case 0x18: case 0x19:
case 0x1a: case 0x1b: case 0x1c:
print_alu_op_start(stream, op0, opA);
util::stream_format(stream, "%02x", opimm);
print_alu_op_end(stream, op0);
return UNSP_DASM_OK;
// pop insns
case 0x29:
if (op == 0x9a90)
util::stream_format(stream, "retf");
else if (op == 0x9a98)
util::stream_format(stream, "reti");
else if (opA+1 < 8 && opA+opN < 8)
util::stream_format(stream, "pop %s, %s from [%s]",
regs[opA+1], regs[opA+opN], regs[opB]);
else
util::stream_format(stream, "<BAD>");
return UNSP_DASM_OK;
// push insns
case 0x2d:
if (opA+1 >= opN && opA < opN+7)
util::stream_format(stream, "push %s, %s to [%s]",
regs[opA+1-opN], regs[opA], regs[opB]);
else
util::stream_format(stream, "<BAD>");
return UNSP_DASM_OK;
// alu, indirect memory
case 0x30: case 0x31: case 0x32: case 0x33:
case 0x34: case 0x36: case 0x38: case 0x39:
case 0x3a: case 0x3b: case 0x3c:
print_alu_op_start(stream, op0, opA);
print_indirect_op(stream, opN, opB);
print_alu_op_end(stream, op0);
return UNSP_DASM_OK;
case 0x3d:
print_indirect_op(stream, opN, opB);
util::stream_format(stream, " = %s", regs[opA]);
return UNSP_DASM_OK;
case 0x40: case 0x41: case 0x42: case 0x43:
case 0x44: case 0x46: case 0x48: case 0x49:
case 0x4a: case 0x4b: case 0x4c:
switch (opN)
{
// alu, register
case 0:
print_alu_op_start(stream, op0, opA);
util::stream_format(stream, "%s", regs[opB]);
print_alu_op_end(stream, op0);
return UNSP_DASM_OK;
// alu, 16-bit immediate
case 1:
if ((op0 == 4 || op0 == 12 || op0 == 6 || op0 == 9) && opA != opB)
{
util::stream_format(stream, "<BAD>");
return UNSP_DASM_OK;
}
if (op0 != 4 && op0 != 12)
util::stream_format(stream, "%s = ", regs[opA]);
print_alu_op3(stream, op0, opB);
util::stream_format(stream, "%04x", ximm);
print_alu_op_end(stream, op0);
return UNSP_DASM_OK;
// alu, direct memory
case 2:
if ((op0 == 4 || op0 == 12 || op0 == 6 || op0 == 9) && opA != opB)
{
util::stream_format(stream, "<BAD>");
return UNSP_DASM_OK;
}
if (op0 != 4 && op0 != 12)
util::stream_format(stream, "%s = ", regs[opA]);
print_alu_op3(stream, op0, opB);
util::stream_format(stream, "[%04x]", ximm);
print_alu_op_end(stream, op0);
return UNSP_DASM_OK;
// alu, direct memory
case 3:
if (op0 == 4 || op0 == 12)
{
util::stream_format(stream, "<BAD>");
return UNSP_DASM_OK;
}
if ((op0 == 6 || op0 == 9) && opA != opB)
{
util::stream_format(stream, "<BAD>");
return UNSP_DASM_OK;
}
util::stream_format(stream, "[%04x] = ", ximm);
print_alu_op3(stream, op0, opB);
util::stream_format(stream, "%s", regs[opA]);
print_alu_op_end(stream, op0);
return UNSP_DASM_OK;
// alu, with shift
default:
print_alu_op_start(stream, op0, opA);
util::stream_format(stream, "%s asr %x", regs[opB], (opN & 3) + 1);
print_alu_op_end(stream, op0);
return UNSP_DASM_OK;
}
case 0x4d:
switch (opN)
{
// alu, direct memory
case 3:
if (opA != opB)
{
util::stream_format(stream, "<BAD>");
return UNSP_DASM_OK;
}
util::stream_format(stream, "[%04x] = %s", ximm, regs[opB]);
return UNSP_DASM_OK;
default:
util::stream_format(stream, "<BAD>");
return UNSP_DASM_OK;
}
// alu, with shift
case 0x50: case 0x51: case 0x52: case 0x53:
case 0x54: case 0x56: case 0x58: case 0x59:
case 0x5a: case 0x5b: case 0x5c:
print_alu_op_start(stream, op0, opA);
if ((opN & 4) == 0)
util::stream_format(stream, "%s lsl %x", regs[opB], (opN & 3) + 1);
else
util::stream_format(stream, "%s lsr %x", regs[opB], (opN & 3) + 1);
print_alu_op_end(stream, op0);
return UNSP_DASM_OK;
// alu, with shift
case 0x60: case 0x61: case 0x62: case 0x63:
case 0x64: case 0x66: case 0x68: case 0x69:
case 0x6a: case 0x6b: case 0x6c:
print_alu_op_start(stream, op0, opA);
if ((opN & 4) == 0)
util::stream_format(stream, "%s rol %x", regs[opB], (opN & 3) + 1);
else
util::stream_format(stream, "%s ror %x", regs[opB], (opN & 3) + 1);
print_alu_op_end(stream, op0);
return UNSP_DASM_OK;
// alu, direct memory
case 0x70: case 0x71: case 0x72: case 0x73:
case 0x74: case 0x76: case 0x78: case 0x79:
case 0x7a: case 0x7b: case 0x7c:
print_alu_op_start(stream, op0, opA);
util::stream_format(stream, "[%02x]", opimm);
print_alu_op_end(stream, op0);
return UNSP_DASM_OK;
case 0x7d:
util::stream_format(stream, "[%02x] = %s", opimm, regs[opA]);
return UNSP_DASM_OK;
case 0x1f:
if (opA == 0)
{
util::stream_format(stream, "call %04x", (opimm << 16) | ximm);
return UNSP_DASM_OK;
}
util::stream_format(stream, "<DUNNO>");
return UNSP_DASM_OK;
case 0x2f: case 0x3f: case 0x6f: case 0x7f:
if (opA == 7 && op1 == 2)
{
util::stream_format(stream, "goto %04x", (opimm << 16) | ximm);
return UNSP_DASM_OK;
}
if (opA == 7 && op1 == 3)
{
util::stream_format(stream, "<DUNNO>");
return UNSP_DASM_OK;
}
util::stream_format(stream, "<DUNNO>");
return UNSP_DASM_OK;
case 0x0f:
switch (opN)
{
case 1:
if (opA == 7)
{
util::stream_format(stream, "<DUNNO>");
return UNSP_DASM_OK;
}
util::stream_format(stream, "mr = %s*%s, us", regs[opA], regs[opB]);
return UNSP_DASM_OK;
default:
util::stream_format(stream, "<DUNNO>");
return UNSP_DASM_OK;
}
case 0x4f:
switch (opN)
{
case 1:
if (opA == 7)
{
util::stream_format(stream, "<DUNNO>");
return UNSP_DASM_OK;
}
util::stream_format(stream, "mr = %s*%s", regs[opA], regs[opB]);
return UNSP_DASM_OK;
default:
util::stream_format(stream, "<DUNNO>");
return UNSP_DASM_OK;
}
case 0x5f:
if (opA != 0)
{
util::stream_format(stream, "<DUNNO>");
return UNSP_DASM_OK;
}
switch (opimm)
{
case 0x00:
util::stream_format(stream, "int off");
return UNSP_DASM_OK;
case 0x01:
util::stream_format(stream, "int irq");
return UNSP_DASM_OK;
case 0x02:
util::stream_format(stream, "int fiq");
return UNSP_DASM_OK;
case 0x03:
util::stream_format(stream, "int fiq,irq");
return UNSP_DASM_OK;
case 0x04:
util::stream_format(stream, "fir_mov on");
return UNSP_DASM_OK;
case 0x05:
util::stream_format(stream, "fir_mov off");
return UNSP_DASM_OK;
case 0x08:
util::stream_format(stream, "irq off");
return UNSP_DASM_OK;
case 0x09:
util::stream_format(stream, "irq on");
return UNSP_DASM_OK;
case 0x0c:
util::stream_format(stream, "fiq off");
return UNSP_DASM_OK;
case 0x0e:
util::stream_format(stream, "fiq on");
return UNSP_DASM_OK;
case 0x25:
util::stream_format(stream, "nop");
return UNSP_DASM_OK;
default:
util::stream_format(stream, "<DUNNO>");
return UNSP_DASM_OK;
}
case 0x0e: case 0x1e: case 0x2e: case 0x3e:
case 0x4e: case 0x5e: case 0x6e: case 0x7e:
util::stream_format(stream, "<DUNNO>");
return UNSP_DASM_OK;
default:
util::stream_format(stream, "<UNHANDLED>");
return UNSP_DASM_OK;
}
util::stream_format(stream, "<inv>");
return UNSP_DASM_OK;
}

View File

@ -1,9 +1,13 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
// license:GPL-2.0
// copyright-holders:Segher Boessenkool
/*****************************************************************************
SunPlus micro'nSP disassembler
Copyright 2008-2017 Segher Boessenkool <segher@kernel.crashing.org>
Licensed under the terms of the GNU GPL, version 2
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
*****************************************************************************/
#ifndef MAME_CPU_UNSP_UNSPDASM_H
@ -22,9 +26,13 @@ public:
offs_t disassemble(std::ostream &stream, offs_t pc, uint16_t op, uint16_t imm16);
private:
static char const *const reg[];
static char const *const jmp[];
static char const *const alu[];
void print_alu_op_start(std::ostream &stream, uint8_t op0, uint8_t opA);
void print_alu_op3(std::ostream &stream, uint8_t op0, uint8_t opB);
void print_alu_op_end(std::ostream &stream, uint8_t op0);
void print_indirect_op(std::ostream &stream, uint8_t opN, uint8_t opB);
static char const *const regs[];
static char const *const jumps[];
};
#endif

View File

@ -167,7 +167,8 @@ void spg2xx_device::device_reset()
memset(m_video_regs, 0, 0x100 * sizeof(uint16_t));
memset(m_io_regs, 0, 0x200 * sizeof(uint16_t));
m_io_regs[0x23] = 0x0028;
//m_io_regs[0x23] = 0x0028;
m_uart_rx_available = false;
m_video_regs[0x36] = 0xffff;
m_video_regs[0x37] = 0xffff;
@ -830,7 +831,7 @@ WRITE_LINE_MEMBER(spg2xx_device::vblank)
#endif
const uint16_t old = VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS;
VIDEO_IRQ_STATUS |= 1;
//VIDEO_IRQ_STATUS |= 1;
LOGMASKED(LOG_IRQS, "Setting video IRQ status to %04x\n", VIDEO_IRQ_STATUS);
const uint16_t changed = old ^ (VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS);
if (changed)
@ -849,18 +850,16 @@ void spg2xx_device::check_video_irq()
void spg2xx_device::uart_rx(uint8_t data)
{
if (m_uart_rx_index < 8)
if (!m_uart_rx_available)
{
m_uart_rx_fifo[m_uart_rx_index] = data;
m_uart_rx_index++;
m_io_regs[0x31] |= 1;
if (m_uart_rx_index > (m_io_regs[0x37] & 7))
if (BIT(m_io_regs[0x30], 6))
{
const uint16_t old = IO_IRQ_STATUS;
IO_IRQ_STATUS |= 0x0100;
const uint16_t changed = old ^ IO_IRQ_STATUS;
if (changed & IO_IRQ_ENABLE)
m_io_regs[0x36] = data;
if (BIT(m_io_regs[0x30], 0))
{
IO_IRQ_STATUS |= 0x0100;
check_irqs(0x0100);
}
}
}
else
@ -947,32 +946,26 @@ READ16_MEMBER(spg2xx_device::io_r)
break;
case 0x31: // UART Status
val = 0x0002 | (m_uart_rx_index ? 1 : 0) | (m_uart_rx_index == 8 ? 0x80 : 0);
val |= 0x81;//(m_uart_rx_available ? 0x81 : 0);
LOGMASKED(LOG_UART, "io_r: UART Status = %04x\n", val);
break;
case 0x36: // UART RX Data
if (m_uart_rx_index)
if (m_uart_rx_available)
{
val = m_uart_rx_fifo[0];
m_uart_rx_fifo[0] = 0;
m_uart_rx_index--;
for (uint8_t i = 0; i < m_uart_rx_index; i++)
{
m_uart_rx_fifo[i] = m_uart_rx_fifo[i + 1];
}
m_uart_rx_available = false;
m_io_regs[0x36] = 0;
}
else
{
m_io_regs[0x37] |= 0x2000;
val = 0;
}
LOGMASKED(LOG_UART, "io_r: UART Rx Data = %04x\n", val);
break;
case 0x37: // UART Rx FIFO Control
val &= ~0x0070;
val |= (m_uart_rx_index > 7 ? 7 : m_uart_rx_index) << 4;
val |= (m_uart_rx_available ? 7 : 0) << 4;
LOGMASKED(LOG_UART, "io_r: UART Rx FIFO Control = %04x\n", val);
break;
@ -1147,12 +1140,14 @@ WRITE16_MEMBER(spg2xx_device::io_w)
if (changed & 0x0013)
{
const uint32_t freq = s_tmb1_freq[hifreq][data & 3];
m_tmb1->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq));
m_cpu->set_timer_interval(0, 27000000 / freq);
//m_tmb1->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq));
}
if (changed & 0x001c)
{
const uint32_t freq = s_tmb2_freq[hifreq][(data >> 2) & 3];
m_tmb2->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq));
m_cpu->set_timer_interval(1, 27000000 / freq);
//m_tmb2->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq));
}
}
break;
@ -1238,16 +1233,16 @@ WRITE16_MEMBER(spg2xx_device::io_w)
case 0x25: // ADC Control
{
LOGMASKED(LOG_IO_WRITES, "io_w: ADC Control = %04x\n", data);
const uint16_t changed = m_io_regs[offset] ^ data;
//const uint16_t changed = m_io_regs[offset] ^ data;
m_io_regs[offset] = data;
if (BIT(changed, 12) && BIT(data, 12) && !BIT(m_io_regs[offset], 1))
//if (BIT(changed, 12) && BIT(data, 12) && !BIT(m_io_regs[offset], 1))
{
m_io_regs[0x27] = 0x80ff;
const uint16_t old = IO_IRQ_STATUS;
IO_IRQ_STATUS |= 0x2000;
const uint16_t changed = IO_IRQ_STATUS ^ old;
if (changed)
check_irqs(changed);
//m_io_regs[0x27] = 0x80ff;
//const uint16_t old = IO_IRQ_STATUS;
//IO_IRQ_STATUS |= 0x2000;
//const uint16_t changed = IO_IRQ_STATUS ^ old;
//if (changed)
//check_irqs(changed);
}
break;
}
@ -1306,23 +1301,23 @@ WRITE16_MEMBER(spg2xx_device::io_w)
static const char* const s_9th_bit[4] = { "0", "1", "Odd", "Even" };
LOGMASKED(LOG_UART, "io_w: UART Control = %04x (TxEn:%d, RxEn:%d, Bits:%d, MultiProc:%d, 9thBit:%s, TxIntEn:%d, RxIntEn:%d\n", data
, BIT(data, 7), BIT(data, 6), BIT(data, 5) ? 9 : 8, BIT(data, 4), s_9th_bit[(data >> 2) & 3], BIT(data, 1), BIT(data, 0));
const uint16_t changed = m_io_regs[offset] ^ data;
//const uint16_t changed = m_io_regs[offset] ^ data;
m_io_regs[offset] = data;
if (!BIT(data, 6))
{
m_uart_rx_index = 0;
memset(m_uart_rx_fifo, 0, 8);
}
if (BIT(changed, 7) && BIT(data, 7))
{
m_io_regs[0x31] |= 0x0002;
m_uart_rx_available = false;
m_io_regs[0x36] = 0;
}
//if (BIT(changed, 7) && BIT(data, 7))
//{
// m_io_regs[0x31] |= 0x0002;
//}
break;
}
case 0x31: // UART Status
LOGMASKED(LOG_UART, "io_w: UART Status = %04x\n", data);
//m_io_regs[offset] &= ~data;
m_io_regs[offset] &= ~data;
break;
case 0x33: // UART Baud Rate
@ -1333,6 +1328,7 @@ WRITE16_MEMBER(spg2xx_device::io_w)
case 0x35: // UART TX Data
LOGMASKED(LOG_UART, "io_w: UART Tx Data = %02x\n", data & 0x00ff);
m_io_regs[offset] = data;
m_io_regs[0x31] |= 2;
m_uart_tx((uint8_t)data);
break;
@ -1345,8 +1341,8 @@ WRITE16_MEMBER(spg2xx_device::io_w)
, BIT(data, 15), BIT(data, 14), BIT(data, 13), (data >> 4) & 7, data & 7);
if (data & 0x8000)
{
m_uart_rx_index = 0;
memset(m_uart_rx_fifo, 0, 8);
m_uart_rx_available = false;
m_io_regs[0x36] = 0;
}
m_io_regs[offset] &= ~data & 0x6000;
m_io_regs[offset] &= ~0x0007;
@ -1394,6 +1390,18 @@ WRITE16_MEMBER(spg2xx_device::io_w)
m_io_regs[offset] = data;
break;
case 0x60: // SPECIAL INTERRUPT HAX - REMOVE BEFORE CHECKIN
m_io_regs[0x22] |= data;
break;
case 0x61: // SPECIAL INTERRUPT HAX - REMOVE BEFORE CHECKIN
m_video_regs[0x63] |= data;
break;
case 0x62: // SPECIAL INTERRUPT HAX - REMOVE BEFORE CHECKIN
m_io_regs[0x22] |= data;
break;
case 0x100: // DMA Source (lo)
LOGMASKED(LOG_DMA, "io_w: DMA Source (lo) = %04x\n", data);
m_io_regs[offset] = data;
@ -1427,17 +1435,17 @@ void spg2xx_device::device_timer(emu_timer &timer, device_timer_id id, int param
{
case TIMER_TMB1:
{
LOGMASKED(LOG_TIMERS, "TMB1 elapsed, setting IRQ Status bit 0 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 1, IO_IRQ_ENABLE);
IO_IRQ_STATUS |= 1;
check_irqs(0x0001);
//LOGMASKED(LOG_TIMERS, "TMB1 elapsed, setting IRQ Status bit 0 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 1, IO_IRQ_ENABLE);
//IO_IRQ_STATUS |= 1;
//check_irqs(0x0001);
break;
}
case TIMER_TMB2:
{
LOGMASKED(LOG_TIMERS, "TMB2 elapsed, setting IRQ Status bit 1 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 2, IO_IRQ_ENABLE);
IO_IRQ_STATUS |= 2;
check_irqs(0x0002);
//LOGMASKED(LOG_TIMERS, "TMB2 elapsed, setting IRQ Status bit 1 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 2, IO_IRQ_ENABLE);
//IO_IRQ_STATUS |= 2;
//check_irqs(0x0002);
break;
}
@ -1468,6 +1476,9 @@ void spg2xx_device::check_irqs(const uint16_t changed)
// m_cpu->set_input_line(UNSP_IRQ1_LINE, ASSERT_LINE);
// }
if (true)
return;
if (changed & 0x0c00) // Timer A, Timer B IRQ
{
m_cpu->set_input_line(UNSP_IRQ2_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? ASSERT_LINE : CLEAR_LINE);

View File

@ -225,16 +225,16 @@ protected:
AUDIO_ADPCM36_MASK = 0x8000,
AUDIO_PHASE_HIGH = 0x200,
AUDIO_PHASE_HIGH_MASK = 0x0007,
AUDIO_PHASE_HIGH_MASK = 0xffff,
AUDIO_PHASE_ACCUM_HIGH = 0x201,
AUDIO_PHASE_ACCUM_HIGH_MASK = 0x0007,
AUDIO_PHASE_ACCUM_HIGH_MASK = 0xffff,
AUDIO_TARGET_PHASE_HIGH = 0x202,
AUDIO_TARGET_PHASE_HIGH_MASK= 0x0007,
AUDIO_TARGET_PHASE_HIGH_MASK= 0xffff,
AUDIO_RAMP_DOWN_CLOCK = 0x203,
AUDIO_RAMP_DOWN_CLOCK_MASK = 0x0007,
AUDIO_RAMP_DOWN_CLOCK_MASK = 0xffff,
AUDIO_PHASE = 0x204,
AUDIO_PHASE_ACCUM = 0x205,
@ -439,8 +439,7 @@ protected:
uint16_t m_audio_curr_beat_base_count;
uint16_t m_io_regs[0x200];
uint8_t m_uart_rx_fifo[8];
uint8_t m_uart_rx_index;
bool m_uart_rx_available;
uint16_t m_video_regs[0x100];
size_t m_sprite_limit;
@ -468,7 +467,7 @@ protected:
sound_stream *m_stream;
oki_adpcm_state m_adpcm[16];
required_device<cpu_device> m_cpu;
required_device<unsp_device> m_cpu;
required_device<screen_device> m_screen;
required_shared_ptr<uint16_t> m_scrollram;
required_shared_ptr<uint16_t> m_paletteram;

View File

@ -186,7 +186,7 @@ public:
: spg2xx_game_state(mconfig, type, tag)
, m_cart(*this, "cartslot")
, m_bankdev(*this, "bank")
, m_cart_banks(*this, "cartbank%u", 0U)
, m_system_region(*this, "maincpu")
{ }
void vsmile(machine_config &config);
@ -218,9 +218,9 @@ private:
DECLARE_READ16_MEMBER(bank2_r);
DECLARE_READ16_MEMBER(bank3_r);
optional_device<generic_slot_device> m_cart;
memory_region *m_cart_rom;
required_device<address_map_bank_device> m_bankdev;
optional_memory_bank_array<4> m_cart_banks;
memory_region *m_cart_region;
required_memory_region m_system_region;
emu_timer *m_pad_timer;
uint8_t m_pad_counter;
@ -248,7 +248,7 @@ private:
virtual void machine_reset() override;
optional_device<generic_slot_device> m_cart;
memory_region *m_cart_rom;
memory_region *m_cart_region;
};
#define VERBOSE_LEVEL (4)
@ -340,7 +340,7 @@ void vsmile_state::device_timer(emu_timer &timer, device_timer_id id, int param,
if (m_pad_counter >= 100)
{
m_pad_counter = 0;
m_spg->uart_rx(0x55);
//m_spg->uart_rx(0x55);
}
}
}
@ -362,59 +362,55 @@ void vsmile_state::device_timer(emu_timer &timer, device_timer_id id, int param,
READ16_MEMBER(vsmile_state::bank0_r)
{
const uint16_t data = ((uint16_t*)m_cart_rom->base())[offset];
//printf("bank0_r: %06x: %04x\n", offset, data);
return data;
return ((uint16_t*)m_cart_region->base())[offset];
}
READ16_MEMBER(vsmile_state::bank1_r)
{
const uint16_t data = ((uint16_t*)m_cart_rom->base())[offset + 0x100000];
//printf("bank1_r: %06x: %04x\n", offset + 0x100000, data);
return data;
return ((uint16_t*)m_cart_region->base())[offset + 0x100000];
}
READ16_MEMBER(vsmile_state::bank2_r)
{
const uint16_t data = ((uint16_t*)m_cart_rom->base())[offset + 0x200000];
//printf("bank2_r: %06x: %04x\n", offset + 0x200000, data);
return data;
return ((uint16_t*)m_cart_region->base())[offset + 0x200000];
}
READ16_MEMBER(vsmile_state::bank3_r)
{
const uint16_t data = ((uint16_t*)memregion("maincpu")->base())[offset];
//printf("bank3_r: %06x: %04x\n", offset + 0x300000, data);
return data;
return ((uint16_t*)m_system_region->base())[offset];
}
READ16_MEMBER(vsmile_state::portb_r)
{
//const uint8_t inputs = m_io_p2->read();
//const uint16_t input_bits = BIT(inputs, 0) ? VSMILE_PORTB_ON_SW : 0;
const uint16_t data = VSMILE_PORTB_ON_SW | (m_cart && m_cart->exists() ? VSMILE_PORTB_CART : 0);
//const uint16_t data = VSMILE_PORTB_ON_SW | VSMILE_PORTB_OFF_SW | (m_cart && m_cart->exists() ? VSMILE_PORTB_CART : 0);
//logerror("V.Smile Port B read %04x, mask %04x\n", data, mem_mask);
//printf("V.Smile Port B read %04x, mask %04x\n", data, mem_mask);
return data;
return m_portb_data;// | data;
}
READ16_MEMBER(vsmile_state::portc_r)
{
const uint16_t data = VSMILE_PORTC_LOGO | 0x0004;
uint16_t data = 0x0004;
if (m_portc_data & 0x0100)
data |= 0x0400;
if (m_portc_data & 0x0200)
data |= 0x1000;
//logerror("V.Smile Port C read %04x, mask %04x\n", data, mem_mask);
return data;
return (m_portc_data & ~0x000f) | data;
}
WRITE16_MEMBER(vsmile_state::portb_w)
{
m_portb_data = data & mem_mask;
m_portb_data = data;//(m_portb_data &~ mem_mask) | (data & mem_mask);
//logerror("V.Smile Port B write %04x, mask %04x\n", m_portb_data, mem_mask);
//printf("V.Smile Port B write %04x, mask %04x\n", m_portb_data, mem_mask);
}
WRITE16_MEMBER(vsmile_state::portc_w)
{
m_portc_data = data & mem_mask;
m_portc_data = data;//(m_portc_data &~ mem_mask) | (data & mem_mask);
//logerror("V.Smile Port C write %04x, mask %04x\n", m_portc_data, mem_mask);
//printf("V.Smile Port C write %04x, mask %04x\n", m_portc_data, mem_mask);
//printf("%02x ", data >> 8);
@ -422,26 +418,22 @@ WRITE16_MEMBER(vsmile_state::portc_w)
WRITE8_MEMBER(vsmile_state::uart_tx)
{
//logerror("UART Tx: %02x\n", data);
logerror("UART Tx: %02x\n", data);
}
WRITE8_MEMBER(vsmile_state::chip_sel_w)
{
//logerror("Chip select mode: %d\n", data);
const uint16_t cart_offset = m_cart && m_cart->exists() ? 4 : 0;
switch (data)
{
case 0:
//logerror("Setting bank %d\n", cart_offset);
m_bankdev->set_bank(cart_offset);
break;
case 1:
//logerror("Setting bank %d\n", 1 + cart_offset);
m_bankdev->set_bank(1 + cart_offset);
break;
case 2:
case 3:
//logerror("Setting bank %d\n", 2 + cart_offset);
m_bankdev->set_bank(2 + cart_offset);
break;
}
@ -499,15 +491,10 @@ void vsmile_state::banked_map(address_map &map)
map(0x0a00000, 0x0afffff).rom().region("maincpu", 0);
map(0x0b00000, 0x0bfffff).rom().region("maincpu", 0);
map(0x1000000, 0x10fffff).bankr("cartbank0");
map(0x1100000, 0x11fffff).bankr("cartbank0");
map(0x1200000, 0x12fffff).bankr("cartbank0");
map(0x1300000, 0x13fffff).bankr("cartbank0");
map(0x1000000, 0x13fffff).r(FUNC(vsmile_state::bank0_r));
map(0x1400000, 0x14fffff).bankr("cartbank0");
map(0x1500000, 0x15fffff).bankr("cartbank0");
map(0x1600000, 0x16fffff).bankr("cartbank1");
map(0x1700000, 0x17fffff).bankr("cartbank1");
map(0x1400000, 0x15fffff).r(FUNC(vsmile_state::bank0_r));
map(0x1600000, 0x17fffff).r(FUNC(vsmile_state::bank1_r));
map(0x1800000, 0x18fffff).r(FUNC(vsmile_state::bank0_r));
map(0x1900000, 0x19fffff).r(FUNC(vsmile_state::bank1_r));
@ -759,8 +746,8 @@ void spg2xx_cart_state::machine_start()
if (m_cart && m_cart->exists())
{
std::string region_tag;
m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
m_bank->configure_entries(0, ceilf((float)m_cart_rom->bytes() / 0x800000), m_cart_rom->base(), 0x800000);
m_cart_region = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
m_bank->configure_entries(0, ceilf((float)m_cart_region->bytes() / 0x800000), m_cart_region->base(), 0x800000);
m_bank->set_entry(0);
}
}
@ -771,22 +758,7 @@ void vsmile_state::machine_start()
if (m_cart && m_cart->exists())
{
std::string region_tag;
m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
const uint32_t banks = (m_cart_rom->bytes() + 0x1fffff) / 0x200000;
for (uint32_t i = 0; i < 2; i++)
{
m_cart_banks[i]->configure_entries(0, banks, m_cart_rom->base(), 0x200000);
m_cart_banks[i]->set_entry(i % banks);
}
}
else
{
for (uint32_t i = 0; i < 2; i++)
{
m_cart_rom = memregion("maincpu");
m_cart_banks[i]->configure_entries(0, (m_cart_rom->bytes() + 0x1fffff) / 0x200000, m_cart_rom->base(), 0x200000);
m_cart_banks[i]->set_entry(0);
}
m_cart_region = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
}
m_bankdev->set_bank(m_cart && m_cart->exists() ? 4 : 0);