mirror of
https://github.com/holub/mame
synced 2025-05-06 14:25:54 +03:00
(MESS) Added preliminary S+core CPU emulation. [Sandro Ronco]
(MESS) New NOT WORKING system ----------------------- - Mattel HyperScan [Sandro Ronco]
This commit is contained in:
parent
26b4b109ff
commit
dbb4595fcc
5
.gitattributes
vendored
5
.gitattributes
vendored
@ -794,6 +794,10 @@ src/emu/cpu/sc61860/sctable.c svneol=native#text/plain
|
||||
src/emu/cpu/scmp/scmp.c svneol=native#text/plain
|
||||
src/emu/cpu/scmp/scmp.h svneol=native#text/plain
|
||||
src/emu/cpu/scmp/scmpdasm.c svneol=native#text/plain
|
||||
src/emu/cpu/score/score.c svneol=native#text/plain
|
||||
src/emu/cpu/score/score.h svneol=native#text/plain
|
||||
src/emu/cpu/score/scoredsm.c svneol=native#text/plain
|
||||
src/emu/cpu/score/scorem.h svneol=native#text/plain
|
||||
src/emu/cpu/scudsp/scudspdasm.c svneol=native#text/plain
|
||||
src/emu/cpu/se3208/se3208.c svneol=native#text/plain
|
||||
src/emu/cpu/se3208/se3208.h svneol=native#text/plain
|
||||
@ -6317,6 +6321,7 @@ src/mess/drivers/hpz80unk.c svneol=native#text/plain
|
||||
src/mess/drivers/ht68k.c svneol=native#text/plain
|
||||
src/mess/drivers/huebler.c svneol=native#text/plain
|
||||
src/mess/drivers/hx20.c svneol=native#text/plain
|
||||
src/mess/drivers/hyperscan.c svneol=native#text/plain
|
||||
src/mess/drivers/ibm6580.c svneol=native#text/plain
|
||||
src/mess/drivers/ibmpc.c svneol=native#text/plain
|
||||
src/mess/drivers/ie15.c svneol=native#text/plain
|
||||
|
@ -2247,3 +2247,22 @@ endif
|
||||
|
||||
$(CPUOBJ)/scudsp/scudspdasm.o: CPUOBJS += $(CPUOBJ)/scudsp/scudspdasm.c
|
||||
|
||||
|
||||
#-------------------------------------------------
|
||||
# Sunplus Technology S+core
|
||||
#@src/emu/cpu/score/score.h,CPUS += SCORE
|
||||
#-------------------------------------------------
|
||||
|
||||
ifneq ($(filter SCORE,$(CPUS)),)
|
||||
OBJDIRS += $(CPUOBJ)/score
|
||||
CPUOBJS += $(CPUOBJ)/score/score.o
|
||||
DASMOBJS += $(CPUOBJ)/score/scoredsm.o
|
||||
endif
|
||||
|
||||
$(CPUOBJ)/score/score.o: $(CPUSRC)/score/score.c \
|
||||
$(CPUSRC)/score/score.h \
|
||||
$(CPUSRC)/score/scorem.h
|
||||
|
||||
$(CPUOBJ)/score/scoredsm.o: $(CPUSRC)/score/scoredsm.c \
|
||||
$(CPUSRC)/score/scorem.h
|
||||
|
||||
|
1346
src/emu/cpu/score/score.c
Normal file
1346
src/emu/cpu/score/score.c
Normal file
File diff suppressed because it is too large
Load Diff
148
src/emu/cpu/score/score.h
Normal file
148
src/emu/cpu/score/score.h
Normal file
@ -0,0 +1,148 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sunplus Technology S+core
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __SCORE_H__
|
||||
#define __SCORE_H__
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEFINITION
|
||||
//**************************************************************************
|
||||
|
||||
enum
|
||||
{
|
||||
SCORE_PC = 1,
|
||||
SCORE_CEH,
|
||||
SCORE_CEL,
|
||||
SCORE_GPR,
|
||||
SCORE_CR = SCORE_GPR + 0x20,
|
||||
SCORE_SR = SCORE_CR + 0x20,
|
||||
};
|
||||
|
||||
|
||||
// ======================> score7_cpu_device
|
||||
|
||||
class score7_cpu_device : public cpu_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
score7_cpu_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock);
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
|
||||
// device_execute_interface overrides
|
||||
virtual UINT32 execute_min_cycles() const { return 1; }
|
||||
virtual UINT32 execute_max_cycles() const { return 1; }
|
||||
virtual UINT32 execute_input_lines() const { return 64; }
|
||||
virtual void execute_run();
|
||||
virtual void execute_set_input(int inputnum, int state);
|
||||
|
||||
// device_state_interface overrides
|
||||
void state_string_export(const device_state_entry &entry, astring &string);
|
||||
|
||||
// device_memory_interface overrides
|
||||
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
|
||||
|
||||
// device_disasm_interface overrides
|
||||
virtual UINT32 disasm_min_opcode_bytes() const { return 2; }
|
||||
virtual UINT32 disasm_max_opcode_bytes() const { return 4; }
|
||||
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
|
||||
|
||||
private:
|
||||
// helpers
|
||||
bool check_condition_branch(UINT8 bc);
|
||||
bool check_condition(UINT8 bc);
|
||||
INT32 sign_extend(UINT32 data, UINT8 len);
|
||||
UINT32 fetch();
|
||||
UINT8 read_byte(offs_t offset);
|
||||
UINT16 read_word(offs_t offset);
|
||||
UINT32 read_dword(offs_t offset);
|
||||
void write_byte(offs_t offset, UINT8 data);
|
||||
void write_word(offs_t offset, UINT16 data);
|
||||
void write_dword(offs_t offset, UINT32 data);
|
||||
void check_irq();
|
||||
void gen_exception(int cause, UINT32 param = 0);
|
||||
|
||||
offs_t disasm(char *buffer, offs_t pc, UINT32 opcode);
|
||||
char *disasm32(char *buffer, offs_t pc, UINT32 opcode);
|
||||
char *disasm16(char *buffer, offs_t pc, UINT16 opcode);
|
||||
void unemulated_op(const char * op);
|
||||
|
||||
// 32-bit opcodes
|
||||
void op_specialform();
|
||||
void op_iform1();
|
||||
void op_jump();
|
||||
void op_rixform1();
|
||||
void op_branch();
|
||||
void op_iform2();
|
||||
void op_crform();
|
||||
void op_rixform2();
|
||||
void op_addri();
|
||||
void op_andri();
|
||||
void op_orri();
|
||||
void op_lw();
|
||||
void op_lh();
|
||||
void op_lhu();
|
||||
void op_lb();
|
||||
void op_sw();
|
||||
void op_sh();
|
||||
void op_lbu();
|
||||
void op_sb();
|
||||
void op_cache();
|
||||
void op_cenew();
|
||||
void op_undef();
|
||||
|
||||
// 16-bit opcodes
|
||||
void op_rform1();
|
||||
void op_rform2();
|
||||
void op_jform();
|
||||
void op_branch16();
|
||||
void op_ldiu();
|
||||
void op_iform1a();
|
||||
void op_iform1b();
|
||||
|
||||
private:
|
||||
address_space_config m_program_config;
|
||||
address_space * m_program;
|
||||
direct_read_data * m_direct;
|
||||
|
||||
// internal state
|
||||
int m_icount;
|
||||
UINT32 m_pc;
|
||||
UINT32 m_ppc;
|
||||
UINT32 m_op;
|
||||
UINT32 m_gpr[0x20];
|
||||
UINT32 m_cr[0x20];
|
||||
UINT32 m_sr[3];
|
||||
UINT32 m_ce[2];
|
||||
bool m_pending_interrupt[64];
|
||||
|
||||
// opcodes tables
|
||||
typedef void (score7_cpu_device::*op_handler)();
|
||||
static const op_handler s_opcode32_table[4*8];
|
||||
static const op_handler s_opcode16_table[8];
|
||||
|
||||
// mnemonics
|
||||
static const char *const m_cond[16];
|
||||
static const char *const m_tcs[4];
|
||||
static const char *const m_rix1_op[8];
|
||||
static const char *const m_rix2_op[8];
|
||||
static const char *const m_r2_op[16];
|
||||
static const char *const m_i1_op[8];
|
||||
static const char *const m_i2_op[8];
|
||||
static const char *const m_ls_op[8];
|
||||
static const char *const m_i1a_op[8];
|
||||
static const char *const m_i1b_op[8];
|
||||
static const char *const m_cr_op[2];
|
||||
};
|
||||
|
||||
extern const device_type SCORE7;
|
||||
|
||||
#endif /* __SCORE_H__ */
|
292
src/emu/cpu/score/scoredsm.c
Normal file
292
src/emu/cpu/score/scoredsm.c
Normal file
@ -0,0 +1,292 @@
|
||||
/******************************************************************************
|
||||
|
||||
Sunplus Technology S+core disassembler
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "score.h"
|
||||
#include "scorem.h"
|
||||
|
||||
const char *const score7_cpu_device::m_cond[16] = { "cs", "cc", "gtu", "leu", "eq", "ne", "gt", "le", "ge", "lt", "mi", "pl", "vs", "vc", "cnz", "" };
|
||||
const char *const score7_cpu_device::m_tcs[4] = { "teq", "tmi", "", ""};
|
||||
const char *const score7_cpu_device::m_rix1_op[8] = { "lw" ,"lh" ,"lhu" ,"lb" ,"sw" ,"sh" ,"lbu" ,"sb" };
|
||||
const char *const score7_cpu_device::m_rix2_op[8] = { "lw", "lh", "lhu", "lb", "sw", "sh", "lbu", "sb" };
|
||||
const char *const score7_cpu_device::m_r2_op[16] = { "add", "sub", "neg", "cmp", "and", "or", "not", "xor", "lw", "lh", "pop", "lbu", "sw", "sh", "push", "sb" };
|
||||
const char *const score7_cpu_device::m_i1_op[8] = { "addi", "", "cmpi", "", "andi", "ori", "ldi", "" };
|
||||
const char *const score7_cpu_device::m_i2_op[8] = { "addis", "", "cmpis", "", "andis", "oris", "ldis", "" };
|
||||
const char *const score7_cpu_device::m_ls_op[8] = { "lw", "lh", "lhu", "lb", "sw", "sh", "lbu", "sb" };
|
||||
const char *const score7_cpu_device::m_i1a_op[8] = { "addei", "slli", "sdbbp", "srli", "bitclr", "bitset", "bittst", "" };
|
||||
const char *const score7_cpu_device::m_i1b_op[8] = { "lwp", "lhp", "", "lbup", "swp", "shp", "", "sbp" };
|
||||
const char *const score7_cpu_device::m_cr_op[2] = { "mtcr", "mfcr" };
|
||||
|
||||
|
||||
char *score7_cpu_device::disasm32(char *buffer, offs_t pc, UINT32 opcode)
|
||||
{
|
||||
switch((opcode >> 25) & 0x1f)
|
||||
{
|
||||
case 0x00: // Special-form
|
||||
{
|
||||
UINT8 ra = GET_S_RA(opcode);
|
||||
UINT8 rb = GET_S_RB(opcode);
|
||||
UINT8 rd = GET_S_RD(opcode);
|
||||
const char *cu = GET_S_CU(opcode) ? ".c": "";
|
||||
const char *lk = GET_S_LK(opcode) ? "l": "";
|
||||
|
||||
switch(GET_S_FUNC6(opcode))
|
||||
{
|
||||
case 0x00: buffer += sprintf(buffer, "nop"); break;
|
||||
case 0x01: buffer += sprintf(buffer, "syscall 0x%04x", (rd<<10) | (ra << 5) | rb); break;
|
||||
case 0x02: buffer += sprintf(buffer, "trap%s 0x%02x", m_cond[rb & 0x0f], ra); break;
|
||||
case 0x03: buffer += sprintf(buffer, "sdbbp 0x%02x", ra); break;
|
||||
case 0x04: buffer += sprintf(buffer, "br%s%s r%d", m_cond[rb & 0x0f], lk, ra); break;
|
||||
case 0x05: buffer += sprintf(buffer, "pflush"); break;
|
||||
case 0x08: buffer += sprintf(buffer, "add%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x09: buffer += sprintf(buffer, "addc%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x0a: buffer += sprintf(buffer, "sub%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x0b: buffer += sprintf(buffer, "subc%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x0c: buffer += sprintf(buffer, "cmp%s%s r%d, r%d", m_tcs[rd & 3], cu, ra, rb); break;
|
||||
case 0x0d: buffer += sprintf(buffer, "cmpz%s%s r%d, r%d", m_tcs[rd & 3], cu, ra, rb); break;
|
||||
case 0x0f: buffer += sprintf(buffer, "neg%s r%d, r%d", cu, rd, rb); break;
|
||||
case 0x10: buffer += sprintf(buffer, "and%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x11: buffer += sprintf(buffer, "or%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x12: buffer += sprintf(buffer, "not%s r%d, r%d", cu, rd, ra); break;
|
||||
case 0x13: buffer += sprintf(buffer, "xor%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x14: buffer += sprintf(buffer, "bitclr%s r%d, %d", cu, ra, rb); break;
|
||||
case 0x15: buffer += sprintf(buffer, "bitset%s r%d, %d", cu, ra, rb); break;
|
||||
case 0x16: buffer += sprintf(buffer, "bittst%s r%d, %d", cu, ra, rb); break;
|
||||
case 0x17: buffer += sprintf(buffer, "bittgl%s r%d, %d", cu, ra, rb); break;
|
||||
case 0x18: buffer += sprintf(buffer, "sll%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x1a: buffer += sprintf(buffer, "srl%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x1b: buffer += sprintf(buffer, "sra%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x1c: buffer += sprintf(buffer, "ror%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x1d: buffer += sprintf(buffer, "rorc%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x1e: buffer += sprintf(buffer, "rol%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x1f: buffer += sprintf(buffer, "rolc%s r%d, r%d, r%d", cu, rd, ra, rb); break;
|
||||
case 0x20: buffer += sprintf(buffer, "mul r%d, r%d", ra, rb); break;
|
||||
case 0x21: buffer += sprintf(buffer, "mulu r%d, r%d", ra, rb); break;
|
||||
case 0x22: buffer += sprintf(buffer, "div r%d, r%d", ra, rb); break;
|
||||
case 0x23: buffer += sprintf(buffer, "divu r%d, r%d", ra, rb); break;
|
||||
case 0x24:
|
||||
buffer += sprintf(buffer, "mfce%s%s r%d", rb & 2 ? "h" : "", rb & 1 ? "l" : "", rd);
|
||||
if ((rb & 3) == 3) buffer += sprintf(buffer, ", r%d", ra);
|
||||
break;
|
||||
case 0x25:
|
||||
buffer += sprintf(buffer, "mtce%s%s r%d", rb & 2 ? "h" : "", rb & 1 ? "l" : "", rd);
|
||||
if ((rb & 3) == 3) buffer += sprintf(buffer, ", r%d", ra);
|
||||
break;
|
||||
case 0x28: buffer += sprintf(buffer, "mfsr sr%d, r%d", rb, ra); break;
|
||||
case 0x29: buffer += sprintf(buffer, "mtsr r%d, sr%d", ra, rb); break;
|
||||
case 0x2a: buffer += sprintf(buffer, "t%s r%d", m_cond[rb & 0x0f], rb); break;
|
||||
case 0x2b: buffer += sprintf(buffer, "mv%s r%d, r%d", m_cond[rb & 0x0f], rd, ra); break;
|
||||
case 0x2c: buffer += sprintf(buffer, "extsb%s r%d, r%d", cu, rd, ra); break;
|
||||
case 0x2d: buffer += sprintf(buffer, "extsh%s r%d, r%d", cu, rd, ra); break;
|
||||
case 0x2e: buffer += sprintf(buffer, "extzb%s r%d, r%d", cu, rd, ra); break;
|
||||
case 0x2f: buffer += sprintf(buffer, "extzh%s r%d, r%d", cu, rd, ra); break;
|
||||
case 0x30: buffer += sprintf(buffer, "lcb [r%d]+", ra); break;
|
||||
case 0x31: buffer += sprintf(buffer, "lcw r%d, [r%d]+", rd, ra); break;
|
||||
case 0x33: buffer += sprintf(buffer, "lce r%d, [r%d]+", rd, ra); break;
|
||||
case 0x34: buffer += sprintf(buffer, "scb r%d, [r%d]+", rd, ra); break;
|
||||
case 0x35: buffer += sprintf(buffer, "scw r%d, [r%d]+", rd, ra); break;
|
||||
case 0x37: buffer += sprintf(buffer, "sce [r%d]+", ra); break;
|
||||
case 0x38: buffer += sprintf(buffer, "slli r%d, r%d, %d", rd, ra, rb); break;
|
||||
case 0x3a: buffer += sprintf(buffer, "srli r%d, r%d, %d", rd, ra, rb); break;
|
||||
case 0x3b: buffer += sprintf(buffer, "srai r%d, r%d, %d", rd, ra, rb); break;
|
||||
case 0x3c: buffer += sprintf(buffer, "rori%s r%d, r%d, %d", cu, rd, ra, rb); break;
|
||||
case 0x3d: buffer += sprintf(buffer, "roric%s r%d, r%d, %d", cu, rd, ra, rb); break;
|
||||
case 0x3e: buffer += sprintf(buffer, "roli%s r%d, r%d, %d", cu, rd, ra, rb); break;
|
||||
case 0x3f: buffer += sprintf(buffer, "rolic%s r%d, r%d, %d", cu, rd, ra, rb); break;
|
||||
default: buffer += sprintf(buffer, "<undefined special-form 0x%02x>", GET_S_FUNC6(opcode));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x01: // I-form-1
|
||||
switch(GET_I_FUNC3(opcode))
|
||||
{
|
||||
case 0x00:
|
||||
buffer += sprintf(buffer, "%s%s r%d, %d", m_i1_op[GET_I_FUNC3(opcode)], GET_I_CU(opcode) ? ".c": "", GET_I_RD(opcode), sign_extend(GET_I_IMM16(opcode), 16));
|
||||
break;
|
||||
case 0x02: case 0x04: case 0x05: case 0x06:
|
||||
buffer += sprintf(buffer, "%s%s r%d, 0x%04x", m_i1_op[GET_I_FUNC3(opcode)], GET_I_CU(opcode) ? ".c": "", GET_I_RD(opcode), GET_I_IMM16(opcode));
|
||||
break;
|
||||
default:
|
||||
buffer += sprintf(buffer, "<undefined i-form-1 0x%02x>", GET_I_FUNC3(opcode));
|
||||
}
|
||||
break;
|
||||
case 0x02:
|
||||
buffer += sprintf(buffer, "j%s 0x%08x", GET_J_LK(opcode) ? "l": "", (pc & 0xfc000000) | (GET_J_DISP24(opcode) << 1));
|
||||
break;
|
||||
case 0x03: // RIX-form-1
|
||||
buffer += sprintf(buffer, "%s r%d, [R%d, %d]+", m_rix1_op[GET_RIX_FUNC3(opcode)], GET_RIX_RD(opcode), GET_RIX_RA(opcode), sign_extend(GET_RIX_IMM12(opcode), 12));
|
||||
break;
|
||||
case 0x04:
|
||||
buffer += sprintf(buffer, "b%s%s 0x%08x", m_cond[GET_BC_BC(opcode) & 0x0f], GET_BC_LK(opcode) ? "l": "", pc + (sign_extend(GET_BC_DISP19(opcode), 19) << 1));
|
||||
break;
|
||||
case 0x05: // I-form-2
|
||||
switch(GET_I_FUNC3(opcode))
|
||||
{
|
||||
case 0x00: case 0x02:
|
||||
case 0x04: case 0x05: case 0x06:
|
||||
buffer += sprintf(buffer, "%s%s r%d, 0x%04x", m_i2_op[GET_I_FUNC3(opcode)], GET_I_CU(opcode) ? ".c": "", GET_I_RD(opcode), GET_I_IMM16(opcode));
|
||||
break;
|
||||
default:
|
||||
buffer += sprintf(buffer, "<undefined i-form-2 0x%02x>", GET_I_FUNC3(opcode));
|
||||
}
|
||||
break;
|
||||
case 0x06: // CR-form
|
||||
switch(GET_CR_OP(opcode))
|
||||
{
|
||||
case 0x00: case 0x01:
|
||||
buffer += sprintf(buffer, "%s r%d, cr%d", m_cr_op[GET_CR_OP(opcode)], GET_CR_RD(opcode), GET_CR_CR(opcode));
|
||||
break;
|
||||
case 0x84:
|
||||
buffer += sprintf(buffer, "rte");
|
||||
break;
|
||||
default:
|
||||
if ((GET_CR_OP(opcode) & 0xc0) == 0)
|
||||
buffer += sprintf(buffer, "<coprocessor instruction 0x%02x>", GET_CR_OP(opcode) & 0x07);
|
||||
else
|
||||
buffer += sprintf(buffer, "<undefined cr-form 0x%02x>", GET_S_FUNC6(opcode));
|
||||
}
|
||||
break;
|
||||
case 0x07: // RIX-form-2
|
||||
buffer += sprintf(buffer, "%s r%d, [R%d]+, %d", m_rix2_op[GET_RIX_FUNC3(opcode)], GET_RIX_RD(opcode), GET_RIX_RA(opcode), sign_extend(GET_RIX_IMM12(opcode), 12));
|
||||
break;
|
||||
case 0x08:
|
||||
buffer += sprintf(buffer, "addri%s r%d, r%d, %d", GET_RI_CU(opcode) ? ".c": "", GET_RI_RD(opcode), GET_RI_RA(opcode), sign_extend(GET_RI_IMM14(opcode), 14));
|
||||
break;
|
||||
case 0x0c:
|
||||
buffer += sprintf(buffer, "andri%s r%d, r%d, 0x%04x", GET_RI_CU(opcode) ? ".c": "", GET_RI_RD(opcode), GET_RI_RA(opcode), GET_RI_IMM14(opcode));
|
||||
break;
|
||||
case 0x0d:
|
||||
buffer += sprintf(buffer, "orri%s r%d, r%d, 0x%04x", GET_RI_CU(opcode) ? ".c": "", GET_RI_RD(opcode), GET_RI_RA(opcode), GET_RI_IMM14(opcode));
|
||||
break;
|
||||
case 0x10: case 0x11: case 0x12: case 0x13:
|
||||
case 0x14: case 0x15: case 0x16: case 0x17:
|
||||
buffer += sprintf(buffer, "%s r%d, [r%d, %d]", m_ls_op[(opcode >> 25) & 0x07], GET_LS_RD(opcode), GET_LS_RA(opcode), sign_extend(GET_LS_IMM15(opcode), 15));
|
||||
break;
|
||||
case 0x18:
|
||||
buffer += sprintf(buffer, "cache 0x%02x, [r%d, %d]", GET_LS_RD(opcode), GET_LS_RA(opcode), sign_extend(GET_LS_IMM15(opcode), 15));
|
||||
break;
|
||||
case 0x1c:
|
||||
sprintf(buffer,"<CENew op: 0x%x>", opcode);
|
||||
break;
|
||||
default:
|
||||
buffer += sprintf(buffer, "<undefined 32-bit opcode 0x%08x>", opcode);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char *score7_cpu_device::disasm16(char *buffer, offs_t pc, UINT16 opcode)
|
||||
{
|
||||
switch((opcode >> 12) & 0x07)
|
||||
{
|
||||
case 0x00: // R-form-1
|
||||
{
|
||||
UINT8 rd = GET_R_RD(opcode);
|
||||
UINT8 ra = GET_R_RA(opcode);
|
||||
|
||||
switch(GET_R_FUNC4(opcode))
|
||||
{
|
||||
case 0x00: buffer += sprintf(buffer, "nop!"); break;
|
||||
case 0x01: buffer += sprintf(buffer, "mlfh! r%d, r%d", rd, 0x10 + ra); break;
|
||||
case 0x02: buffer += sprintf(buffer, "mhfl! r%d, r%d", 0x10 + rd, ra); break;
|
||||
case 0x03: buffer += sprintf(buffer, "mv! r%d, r%d", rd, ra); break;
|
||||
case 0x04: buffer += sprintf(buffer, "br%s! r%d", m_cond[rd & 0x0f], ra); break;
|
||||
case 0x05: buffer += sprintf(buffer, "t%s!", m_cond[rd & 0x0f]); break;
|
||||
case 0x08: buffer += sprintf(buffer, "sll! r%d, r%d", rd, ra); break;
|
||||
case 0x09: buffer += sprintf(buffer, "addc! r%d, r%d", rd, ra); break;
|
||||
case 0x0a: buffer += sprintf(buffer, "srl! r%d, r%d", rd, ra); break;
|
||||
case 0x0b: buffer += sprintf(buffer, "sra! r%d, r%d", rd, ra); break;
|
||||
case 0x0c: buffer += sprintf(buffer, "br%sl! r%d", m_cond[rd & 0x0f], ra); break;
|
||||
default: buffer += sprintf(buffer, "<undefined r-form-1 0x%02x>", GET_R_FUNC4(opcode));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x02: // R-form-2
|
||||
switch(GET_R_FUNC4(opcode))
|
||||
{
|
||||
case 0: case 1: case 2: case 3:
|
||||
case 4: case 5: case 6: case 7:
|
||||
buffer += sprintf(buffer, "%s! r%d, r%d", m_r2_op[GET_R_FUNC4(opcode)], GET_R_RD(opcode), GET_R_RA(opcode));
|
||||
break;
|
||||
case 0x0a: case 0x0e:
|
||||
buffer += sprintf(buffer, "%s! r%d, [r%d]", m_r2_op[GET_R_FUNC4(opcode)], GET_P_RDG(opcode), GET_P_RAG(opcode));
|
||||
break;
|
||||
default:
|
||||
buffer += sprintf(buffer, "%s! r%d, [r%d]", m_r2_op[GET_R_FUNC4(opcode)], GET_R_RD(opcode), GET_R_RA(opcode));
|
||||
}
|
||||
break;
|
||||
case 0x03:
|
||||
buffer += sprintf(buffer, "j%s! 0x%08x", GET_J_LK(opcode) ? "l": "", (pc & 0xfffff000) | (GET_J_DISP11(opcode) << 1));
|
||||
break;
|
||||
case 0x04:
|
||||
buffer += sprintf(buffer, "b%s! 0x%08x", m_cond[GET_BX_EC(opcode) & 0x0f], pc + sign_extend(GET_BX_DISP8(opcode) << 1, 9));
|
||||
break;
|
||||
case 0x05:
|
||||
buffer += sprintf(buffer, "ldiu! r%d, 0x%02x", GET_I2_RD(opcode), GET_I2_IMM8(opcode));
|
||||
break;
|
||||
case 0x06: // I-form-1a
|
||||
if (GET_I16_FUNC3(opcode) != 7)
|
||||
buffer += sprintf(buffer, "%s! r%d, %d", m_i1a_op[GET_I16_FUNC3(opcode)], GET_I16_RD(opcode), GET_I16_IMM5(opcode));
|
||||
else
|
||||
buffer += sprintf(buffer, "<undefined i-form-1a 0x%02x>", GET_I16_FUNC3(opcode));
|
||||
break;
|
||||
case 0x07: // I-form-1b
|
||||
switch(GET_I16_FUNC3(opcode))
|
||||
{
|
||||
case 0: case 4:
|
||||
buffer += sprintf(buffer, "%s! r%d, %d", m_i1b_op[GET_I16_FUNC3(opcode)], GET_I16_RD(opcode), GET_I16_IMM5(opcode)<<2);
|
||||
break;
|
||||
case 1: case 5:
|
||||
buffer += sprintf(buffer, "%s! r%d, %d", m_i1b_op[GET_I16_FUNC3(opcode)], GET_I16_RD(opcode), GET_I16_IMM5(opcode)<<1);
|
||||
break;
|
||||
case 3: case 7:
|
||||
buffer += sprintf(buffer, "%s! r%d, %d", m_i1b_op[GET_I16_FUNC3(opcode)], GET_I16_RD(opcode), GET_I16_IMM5(opcode));
|
||||
break;
|
||||
default:
|
||||
buffer += sprintf(buffer, "<undefined i-form-1b 0x%02x>", GET_I16_FUNC3(opcode));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
offs_t score7_cpu_device::disasm(char *buffer, offs_t pc, UINT32 opcode)
|
||||
{
|
||||
UINT8 p = (pc & 0x02) ? 0 : (((opcode>>30) & 2) | ((opcode>>15) & 1));
|
||||
|
||||
switch(p)
|
||||
{
|
||||
case 0: // 16-bit + 16-bit instruction
|
||||
buffer = disasm16(buffer, pc, opcode & 0x7fff);
|
||||
break;
|
||||
case 1: // undefined
|
||||
buffer += sprintf(buffer,"<undefined parity-check 0x%08x>", opcode);
|
||||
break;
|
||||
case 2: // parallel conditional execution
|
||||
buffer = disasm16(buffer, pc, opcode & 0x7fff);
|
||||
buffer += sprintf(buffer, " ||");
|
||||
break;
|
||||
case 3: // 32-bit instruction
|
||||
buffer = disasm32(buffer, pc, (opcode & 0x7fff) | ((opcode >> 1) & 0x3fff8000));
|
||||
break;
|
||||
}
|
||||
|
||||
return (p & 0x01) ? 4 : 2;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// disasm_disassemble - call the disassembly
|
||||
// helper function
|
||||
//-------------------------------------------------
|
||||
|
||||
offs_t score7_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
|
||||
{
|
||||
UINT32 opcode = oprom[0] | (oprom[1] << 8) | (oprom[2] << 16) | (oprom[3] << 24);
|
||||
|
||||
return disasm(buffer, pc, opcode);
|
||||
}
|
144
src/emu/cpu/score/scorem.h
Normal file
144
src/emu/cpu/score/scorem.h
Normal file
@ -0,0 +1,144 @@
|
||||
|
||||
// Special-form
|
||||
#define GET_S_FUNC6(op) ((op >> 1) & 0x3f)
|
||||
#define GET_S_RB(op) ((op >> 10) & 0x1f)
|
||||
#define GET_S_RA(op) ((op >> 15) & 0x1f)
|
||||
#define GET_S_RD(op) ((op >> 20) & 0x1f)
|
||||
#define GET_S_CU(op) (op & 0x01)
|
||||
#define GET_S_LK(op) (op & 0x01)
|
||||
|
||||
// I-form
|
||||
#define GET_I_FUNC3(op) ((op >> 17) & 0x07)
|
||||
#define GET_I_IMM16(op) ((op >> 1) & 0xffff)
|
||||
#define GET_I_RD(op) ((op >> 20) & 0x1f)
|
||||
#define GET_I_CU(op) (op & 0x01)
|
||||
|
||||
// RI-form
|
||||
#define GET_RI_IMM14(op) ((op >> 1) & 0x3fff)
|
||||
#define GET_RI_RA(op) ((op >> 15) & 0x1f)
|
||||
#define GET_RI_RD(op) ((op >> 20) & 0x1f)
|
||||
#define GET_RI_CU(op) (op & 0x01)
|
||||
|
||||
// J-form
|
||||
#define GET_J_DISP24(op) ((op >> 1) & 0x00ffffff)
|
||||
#define GET_J_DISP11(op) ((op >> 1) & 0x000007ff)
|
||||
#define GET_J_LK(op) (op & 0x01)
|
||||
|
||||
// BC-form
|
||||
#define GET_BC_DISP19(op) (((op >> 6) & 0x07fe00) | ((op >> 1) & 0x0001ff))
|
||||
#define GET_BC_BC(op) ((op >> 10) & 0x1f)
|
||||
#define GET_BC_LK(op) (op & 0x01)
|
||||
|
||||
// RIX-form
|
||||
#define GET_RIX_FUNC3(op) (op & 0x07)
|
||||
#define GET_RIX_IMM12(op) ((op >> 3) & 0x0fff)
|
||||
#define GET_RIX_RA(op) ((op >> 15) & 0x1f)
|
||||
#define GET_RIX_RD(op) ((op >> 20) & 0x1f)
|
||||
|
||||
// R-form
|
||||
#define GET_R_FUNC4(op) (op & 0x0f)
|
||||
#define GET_R_RA(op) ((op >> 4) & 0x0f)
|
||||
#define GET_R_RD(op) ((op >> 8) & 0x0f)
|
||||
|
||||
// BX-form
|
||||
#define GET_BX_DISP8(op) (op & 0xff)
|
||||
#define GET_BX_EC(op) ((op >> 8) & 0x0f)
|
||||
|
||||
// LS-form
|
||||
#define GET_LS_RD(op) ((op >> 20) & 0x1f)
|
||||
#define GET_LS_RA(op) ((op >> 15) & 0x1f)
|
||||
#define GET_LS_IMM15(op) (op & 0x7fff)
|
||||
|
||||
// I2-form
|
||||
#define GET_I2_RD(op) ((op >> 8) & 0x0f)
|
||||
#define GET_I2_IMM8(op) (op & 0xff)
|
||||
|
||||
// I-form
|
||||
#define GET_I16_FUNC3(op) (op & 0x07)
|
||||
#define GET_I16_RD(op) ((op >> 8) & 0x0f)
|
||||
#define GET_I16_IMM5(op) ((op >> 3) & 0x1f)
|
||||
|
||||
// CR-form
|
||||
#define GET_CR_OP(op) (op & 0xff)
|
||||
#define GET_CR_IMM10(op) ((op >> 5) & 0x3ff)
|
||||
#define GET_CR_CR(op) ((op >> 15) & 0x1f)
|
||||
#define GET_CR_RD(op) ((op >> 20) & 0x1f)
|
||||
|
||||
// PUSH/POP-form
|
||||
#define GET_P_RAG(op) ((op >> 4) & 0x07)
|
||||
#define GET_P_RDG(op) (((op >> 8) & 0x0f) | ((op >> 3) & 0x10))
|
||||
|
||||
|
||||
// flags
|
||||
#define FLAG_V 0x01
|
||||
#define FLAG_C 0x02
|
||||
#define FLAG_Z 0x04
|
||||
#define FLAG_N 0x08
|
||||
#define FLAG_T 0x10
|
||||
|
||||
#define GET_V ((REG_CR & FLAG_V)>>0)
|
||||
#define GET_C ((REG_CR & FLAG_C)>>1)
|
||||
#define GET_Z ((REG_CR & FLAG_Z)>>2)
|
||||
#define GET_N ((REG_CR & FLAG_N)>>3)
|
||||
#define GET_T ((REG_CR & FLAG_T)>>4)
|
||||
|
||||
#define SET_V(f) if (f) REG_CR |= FLAG_V; else REG_CR &= ~FLAG_V;
|
||||
#define SET_C(f) if (f) REG_CR |= FLAG_C; else REG_CR &= ~FLAG_C;
|
||||
#define SET_Z(f) if (f) REG_CR |= FLAG_Z; else REG_CR &= ~FLAG_Z;
|
||||
#define SET_N(f) if (f) REG_CR |= FLAG_N; else REG_CR &= ~FLAG_N;
|
||||
#define SET_T(f) if (f) REG_CR |= FLAG_T; else REG_CR &= ~FLAG_T;
|
||||
|
||||
#define CHECK_Z(r) SET_Z((r)==0)
|
||||
#define CHECK_N(r) SET_N((INT32)(r) < 0)
|
||||
#define CHECK_C_ADD(a,b) SET_C((a) > (0xffffffffu - (b)))
|
||||
#define CHECK_C_SUB(a,b) SET_C((a) >= (b))
|
||||
#define CHECK_V_ADD(a,b,d) SET_V((INT32)(((a) ^ (d)) & ((b) ^ (d))) < 0)
|
||||
#define CHECK_V_SUB(a,b,d) SET_V((INT32)(((a) ^ (b)) & ((a) ^ (d))) < 0)
|
||||
|
||||
|
||||
// registers
|
||||
#define REG_BP m_gpr[2]
|
||||
#define REG_LNK m_gpr[3]
|
||||
#define REG_PSR m_cr[0]
|
||||
#define REG_CR m_cr[1]
|
||||
#define REG_ECR m_cr[2]
|
||||
#define REG_EXCPVEC m_cr[3]
|
||||
#define REG_CCR m_cr[4]
|
||||
#define REG_EPC m_cr[5]
|
||||
#define REG_EMA m_cr[6]
|
||||
#define REG_TLBLOCK m_cr[7]
|
||||
#define REG_TLBPT m_cr[8]
|
||||
#define REG_PEADDR m_cr[9]
|
||||
#define REG_TLBRPT m_cr[10]
|
||||
#define REG_PEVN m_cr[11]
|
||||
#define REG_PECTX m_cr[12]
|
||||
#define REG_LIMPFN m_cr[15]
|
||||
#define REG_LDMPFN m_cr[16]
|
||||
#define REG_PREV m_cr[18]
|
||||
#define REG_DREG m_cr[29]
|
||||
#define REG_DEPC m_cr[30]
|
||||
#define REG_DSAVE m_cr[31]
|
||||
#define REG_CNT m_sr[0]
|
||||
#define REG_LCR m_sr[1]
|
||||
#define REG_SCR m_sr[2]
|
||||
#define REG_CEH m_ce[0]
|
||||
#define REG_CEL m_ce[1]
|
||||
|
||||
|
||||
// exceptions causes
|
||||
#define EXCEPTION_RESET 0
|
||||
#define EXCEPTION_NMI 1
|
||||
#define EXCEPTION_ADEL_INSTRUCTION 2
|
||||
#define EXCEPTION_BUSEL_INSTRUCTION 5
|
||||
#define EXCEPTION_P_EL 6
|
||||
#define EXCEPTION_SYSCALL 7
|
||||
#define EXCEPTION_CCU 8
|
||||
#define EXCEPTION_RI 9
|
||||
#define EXCEPTION_TRAP 10
|
||||
#define EXCEPTION_ADEL_DATA 11
|
||||
#define EXCEPTION_ADES_DATA 12
|
||||
#define EXCEPTION_CEE 16
|
||||
#define EXCEPTION_CPE 17
|
||||
#define EXCEPTION_BUSEL_DATA 18
|
||||
#define EXCEPTION_SWI 19
|
||||
#define EXCEPTION_INTERRUPT 20
|
645
src/mess/drivers/hyperscan.c
Normal file
645
src/mess/drivers/hyperscan.c
Normal file
@ -0,0 +1,645 @@
|
||||
/***************************************************************************
|
||||
|
||||
Mattel HyperScan
|
||||
|
||||
08/17/2013 Skeleton driver by Sandro Ronco
|
||||
|
||||
SPG290 Interrupt:
|
||||
|
||||
Vector Source
|
||||
63 SPU FIQ
|
||||
62 SPU Beatirq
|
||||
61 SPU Envirq
|
||||
60 CD servo
|
||||
59 ADC gain overflow / ADC recorder / FIFO overflow
|
||||
58 General purpose ADC
|
||||
57 Timer base
|
||||
56 Timer
|
||||
55 TV vblanking start
|
||||
54 LCD vblanking start
|
||||
53 PPU vblanking start
|
||||
52 TV
|
||||
51 Sensor frame end
|
||||
50 Sensor coordinate hit
|
||||
49 Sensor motion frame end
|
||||
48 Sensor capture done + sensor debug IRQ
|
||||
47 TV coordinate hit
|
||||
46 PPU coordinate hit
|
||||
45 USB host+device
|
||||
44 SIO
|
||||
43 SPI
|
||||
42 Uart (IrDA)
|
||||
41 NAND
|
||||
40 SD
|
||||
39 I2C master
|
||||
38 I2S slave
|
||||
37 APBDMA CH1
|
||||
36 APBDMA CH2
|
||||
35 LDM_DMA
|
||||
34 BLN_DMA
|
||||
33 APBDMA CH3
|
||||
32 APBDMA CH4
|
||||
31 Alarm + HMS
|
||||
30 MP4
|
||||
29 C3 (ECC module)
|
||||
28 GPIO
|
||||
27 Bufctl (for debug) + TV/PPU vblanking end (for debug)
|
||||
26 RESERVED1
|
||||
25 RESERVED2
|
||||
24 RESERVED3
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/score/score.h"
|
||||
|
||||
|
||||
#define LOG_SPG290_REGISTER_ACCESS (1)
|
||||
|
||||
|
||||
|
||||
class hyperscan_state : public driver_device
|
||||
{
|
||||
public:
|
||||
hyperscan_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu")
|
||||
{ }
|
||||
|
||||
required_device<score7_cpu_device> m_maincpu;
|
||||
|
||||
virtual void machine_start();
|
||||
virtual void machine_reset();
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
|
||||
UINT32 spg290_screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
DECLARE_READ32_MEMBER(spg290_regs_r);
|
||||
DECLARE_WRITE32_MEMBER(spg290_regs_w);
|
||||
void spg290_timers_update();
|
||||
void spg290_vblank_irq(screen_device &screen, bool state);
|
||||
inline UINT32 spg290_read_mem(UINT32 offset);
|
||||
inline void spg290_write_mem(UINT32 offset, UINT32 data);
|
||||
void spg290_argb1555(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16 posy, UINT16 posx, UINT16 argb);
|
||||
void spg290_rgb565(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16 posy, UINT16 posx, UINT16 rgb, UINT32 transrgb);
|
||||
void spg290_blit_sprite(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT32 control, UINT32 attribute, UINT32 *palettes, UINT32 buf_start);
|
||||
void spg290_blit_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT32 control, UINT32 attribute, int posy, int posx, UINT32 nptr, UINT32 buf_start, UINT32 transrgb);
|
||||
void spg290_blit_character(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT32 control, UINT32 attribute, int posy, int posx, UINT32 nptr, UINT32 buf_start, UINT32 transrgb);
|
||||
|
||||
private:
|
||||
static const device_timer_id TIMER_SPG290 = 0;
|
||||
static const device_timer_id TIMER_I2C = 1;
|
||||
|
||||
struct spg290_miu
|
||||
{
|
||||
UINT32 status;
|
||||
};
|
||||
|
||||
struct spg290_ppu
|
||||
{
|
||||
UINT32 control;
|
||||
UINT32 irq_control;
|
||||
UINT32 irq_status;
|
||||
UINT32 sprite_max;
|
||||
UINT32 sprite_buf_start;
|
||||
UINT32 frame_buff[3];
|
||||
UINT32 palettes[0x200];
|
||||
UINT32 tx_hoffset[0x200];
|
||||
UINT32 tx_hcomp[0x200];
|
||||
UINT32 transrgb;
|
||||
|
||||
struct ppu_spite
|
||||
{
|
||||
UINT32 control;
|
||||
UINT32 attribute;
|
||||
} sprites[0x200];
|
||||
|
||||
struct ppu_tx
|
||||
{
|
||||
UINT32 control;
|
||||
UINT32 attribute;
|
||||
UINT32 posx;
|
||||
UINT32 posy;
|
||||
UINT32 nptr;
|
||||
UINT32 buf_start[3];
|
||||
} txs[3];
|
||||
};
|
||||
|
||||
struct spg290_timer
|
||||
{
|
||||
UINT32 control;
|
||||
UINT32 control2;
|
||||
UINT16 preload;
|
||||
UINT16 counter;
|
||||
};
|
||||
|
||||
struct spg290_i2c
|
||||
{
|
||||
UINT32 config;
|
||||
UINT32 irq_control;
|
||||
UINT32 clock;
|
||||
UINT8 count;
|
||||
UINT32 id;
|
||||
UINT32 port_addr;
|
||||
UINT32 wdata;
|
||||
UINT32 rdata;
|
||||
};
|
||||
|
||||
spg290_miu m_miu;
|
||||
spg290_ppu m_ppu;
|
||||
spg290_timer m_timers[6];
|
||||
spg290_i2c m_i2c;
|
||||
emu_timer * m_update_timer;
|
||||
emu_timer * m_i2c_timer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#if LOG_SPG290_REGISTER_ACCESS
|
||||
static void log_spg290_regs(UINT8 module, UINT16 reg, UINT32 mem_mask, bool write, UINT32 data=0)
|
||||
{
|
||||
static const char *const modules_name[] =
|
||||
{
|
||||
"CSI", "PPU", "JPG", "TV", "LCD", "SPU", "CD", "MIU", "APBDMA", "BUFCTL","IRQCTL", "GPUBUF", "LDMDMA",
|
||||
"BLNDMA", "TPGBUF", "AHBDEC", "GPIO", "SPI", "SIO", "I2C", "I2S", "UART", "TIMERS/RTC", "WDOG", "SD",
|
||||
"FLASH", "ADC", "USB device", "USB host", "Reserved", "Reserved", "Reserved", "SFTCFG", "CKG", "MP4",
|
||||
"MIU2", "ECC"
|
||||
};
|
||||
|
||||
if (module < 0x25)
|
||||
logerror("SPG: %-10s", modules_name[module]);
|
||||
else
|
||||
logerror("SPG: mod 0x%02x ", module);
|
||||
|
||||
if (!write)
|
||||
logerror(" R 0x%04x", reg);
|
||||
else
|
||||
logerror(" W 0x%04x = 0x%08x", reg, data);
|
||||
|
||||
if (mem_mask != 0xffffffffu)
|
||||
logerror(" (0x%08x)\n", mem_mask);
|
||||
else
|
||||
logerror("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
READ32_MEMBER(hyperscan_state::spg290_regs_r)
|
||||
{
|
||||
UINT32 addr = offset << 2;
|
||||
UINT32 data = 0;
|
||||
|
||||
if (addr == 0x010000) // PPU Control
|
||||
{
|
||||
data = m_ppu.control;
|
||||
}
|
||||
else if (addr == 0x010084) // PPU IRQ Status
|
||||
{
|
||||
data = m_ppu.irq_status;
|
||||
}
|
||||
if (addr == 0x07006c) // MIU Status
|
||||
{
|
||||
data = m_miu.status;
|
||||
}
|
||||
else if ((addr & 0xff0fff) == 0x160000) // Timer X Status
|
||||
{
|
||||
int idx = (offset>>10) & 0x0f;
|
||||
data = m_timers[idx].control;
|
||||
}
|
||||
else if(addr == 0x130024) // I2C interrupt
|
||||
{
|
||||
data = m_i2c.irq_control;
|
||||
}
|
||||
else if(addr == 0x130034) // I2C write data
|
||||
{
|
||||
data = m_i2c.wdata;
|
||||
}
|
||||
else if(addr == 0x130038) // I2C data data
|
||||
{
|
||||
data = m_i2c.rdata;
|
||||
}
|
||||
|
||||
#if LOG_SPG290_REGISTER_ACCESS
|
||||
//else
|
||||
{
|
||||
if (!space.debugger_access())
|
||||
log_spg290_regs((offset >> 14) & 0xff, (offset<<2) & 0xffff, mem_mask, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER(hyperscan_state::spg290_regs_w)
|
||||
{
|
||||
UINT32 addr = offset << 2;
|
||||
|
||||
if (addr == 0x010000) // PPU Control
|
||||
{
|
||||
COMBINE_DATA(&m_ppu.control);
|
||||
}
|
||||
else if (addr == 0x010008) // PPU Max Sprites
|
||||
{
|
||||
COMBINE_DATA(&m_ppu.sprite_max);
|
||||
}
|
||||
else if (addr == 0x010010) // PPU Max Sprites
|
||||
{
|
||||
COMBINE_DATA(&m_ppu.transrgb);
|
||||
}
|
||||
else if (addr == 0x0100d0) // Sprites buffer start
|
||||
{
|
||||
COMBINE_DATA(&m_ppu.sprite_buf_start);
|
||||
}
|
||||
else if (addr == 0x010020 || addr == 0x01003c || addr == 0x010058) // Text Layers x pos
|
||||
{
|
||||
int idx = (((offset>>3) & 3) | ((offset>>4) & 1)) - 1;
|
||||
COMBINE_DATA(&m_ppu.txs[idx].posx);
|
||||
}
|
||||
else if (addr == 0x010024 || addr == 0x010040 || addr == 0x01005c) // Text Layers y pos
|
||||
{
|
||||
int idx = (((offset>>3) & 3) | ((offset>>4) & 1)) - 1;
|
||||
COMBINE_DATA(&m_ppu.txs[idx].posy);
|
||||
}
|
||||
else if (addr == 0x010028 || addr == 0x010044 || addr == 0x010060) // Text Layers attribute
|
||||
{
|
||||
int idx = ((offset>>3) & 3) - 1;
|
||||
COMBINE_DATA(&m_ppu.txs[idx].attribute);
|
||||
}
|
||||
else if (addr == 0x01002c || addr == 0x010048 || addr == 0x010064) // Text Layers control
|
||||
{
|
||||
int idx = ((offset>>3) & 3) - 1;
|
||||
COMBINE_DATA(&m_ppu.txs[idx].control);
|
||||
}
|
||||
else if (addr == 0x010030 || addr == 0x01004c || addr == 0x010068) // Text Layers number ptr
|
||||
{
|
||||
int idx = ((offset>>3) & 3) - 1;
|
||||
COMBINE_DATA(&m_ppu.txs[idx].nptr);
|
||||
}
|
||||
else if (addr == 0x010080) // PPU IRQ Control
|
||||
{
|
||||
COMBINE_DATA(&m_ppu.irq_control);
|
||||
}
|
||||
else if (addr == 0x010084) // PPU IRQ ack
|
||||
{
|
||||
if (ACCESSING_BITS_0_7)
|
||||
m_ppu.irq_status &= ~data;
|
||||
}
|
||||
else if (addr >= 0x0100a0 && addr <= 0x0100a8) // Tx1 buffer start
|
||||
{
|
||||
COMBINE_DATA(&m_ppu.txs[0].buf_start[offset & 3]);
|
||||
}
|
||||
else if (addr >= 0x0100ac && addr <= 0x0100b4) // Tx2 buffer start
|
||||
{
|
||||
COMBINE_DATA(&m_ppu.txs[1].buf_start[(offset+1) & 3]);
|
||||
}
|
||||
else if (addr >= 0x0100b8 && addr <= 0x0100c0) // Tx3 buffer starts
|
||||
{
|
||||
COMBINE_DATA(&m_ppu.txs[2].buf_start[(offset+2) & 3]);
|
||||
}
|
||||
else if ((addr & 0xfff000) == 0x011000) // Palettes
|
||||
{
|
||||
COMBINE_DATA(&m_ppu.palettes[offset & 0x01ff]);
|
||||
}
|
||||
else if ((addr & 0xfff000) == 0x012000) // Tx horizontal offset
|
||||
{
|
||||
COMBINE_DATA(&m_ppu.tx_hoffset[offset & 0x01ff]);
|
||||
}
|
||||
else if ((addr & 0xfff000) == 0x013000) // Tx horizontal compression
|
||||
{
|
||||
COMBINE_DATA(&m_ppu.tx_hcomp[offset & 0x01ff]);
|
||||
}
|
||||
else if ((addr & 0xfff000) == 0x014000) // Sprite Control Registers
|
||||
{
|
||||
int idx = (offset>>1) & 0x1ff;
|
||||
if (offset & 1)
|
||||
COMBINE_DATA(&m_ppu.sprites[idx].attribute);
|
||||
else
|
||||
COMBINE_DATA(&m_ppu.sprites[idx].control);
|
||||
}
|
||||
else if (addr == 0x07005c) // MIU Status
|
||||
{
|
||||
COMBINE_DATA(&m_miu.status);
|
||||
}
|
||||
else if ((addr & 0xff0fff) == 0x160000) // Timer X Control 1
|
||||
{
|
||||
int idx = (offset>>10) & 0x07;
|
||||
COMBINE_DATA(&m_timers[idx].control);
|
||||
|
||||
if (ACCESSING_BITS_24_31)
|
||||
m_timers[idx].control &= ~(data & 0x04000000); // Timers IRQ ack
|
||||
}
|
||||
else if ((addr & 0xff0fff) == 0x160004) // Timer X Control 2
|
||||
{
|
||||
int idx = (offset>>10) & 0x07;
|
||||
COMBINE_DATA(&m_timers[idx].control2);
|
||||
}
|
||||
else if ((addr & 0xff0fff) == 0x160008) // Timer X Preload
|
||||
{
|
||||
int idx = (offset>>10) & 0x07;
|
||||
COMBINE_DATA(&m_timers[idx].preload);
|
||||
}
|
||||
else if (addr == 0x2100e4) // Timer Source Clock Selection
|
||||
{
|
||||
UINT32 timers_clk = XTAL_27MHz / ((data & 0xff) + 1);
|
||||
m_update_timer->adjust(attotime::from_hz(timers_clk), 0, attotime::from_hz(timers_clk));
|
||||
}
|
||||
else if(addr == 0x130020) // I2C configuration
|
||||
{
|
||||
COMBINE_DATA(&m_i2c.config);
|
||||
}
|
||||
else if(addr == 0x130024) // I2C interrupt
|
||||
{
|
||||
COMBINE_DATA(&m_i2c.irq_control);
|
||||
|
||||
if (ACCESSING_BITS_0_7)
|
||||
m_i2c.irq_control &= ~(data & 0x00000001); // I2C IRQ ack
|
||||
}
|
||||
else if(addr == 0x130028) // I2C clock setting
|
||||
{
|
||||
COMBINE_DATA(&m_i2c.clock);
|
||||
UINT32 i2c_clk = XTAL_27MHz / ((m_i2c.clock & 0x3ff) + 1);
|
||||
m_i2c_timer->adjust(attotime::from_hz(i2c_clk), 0, attotime::from_hz(i2c_clk));
|
||||
}
|
||||
else if(addr == 0x13002c) // I2C ID
|
||||
{
|
||||
COMBINE_DATA(&m_i2c.id);
|
||||
}
|
||||
else if(addr == 0x130030) // I2C port address
|
||||
{
|
||||
COMBINE_DATA(&m_i2c.port_addr);
|
||||
}
|
||||
else if(addr == 0x130034) // I2C write data
|
||||
{
|
||||
COMBINE_DATA(&m_i2c.wdata);
|
||||
}
|
||||
else if(addr == 0x130038) // I2C data data
|
||||
{
|
||||
COMBINE_DATA(&m_i2c.rdata);
|
||||
}
|
||||
else if(addr == 0x150000) // UART data
|
||||
{
|
||||
if (ACCESSING_BITS_0_7)
|
||||
printf("%c", data & 0xff);
|
||||
}
|
||||
|
||||
#if LOG_SPG290_REGISTER_ACCESS
|
||||
//else
|
||||
{
|
||||
if (!space.debugger_access())
|
||||
log_spg290_regs((offset >> 14) & 0xff, (offset<<2) & 0xffff, mem_mask, true, data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline UINT32 hyperscan_state::spg290_read_mem(UINT32 offset)
|
||||
{
|
||||
return m_maincpu->space(0).read_dword(offset);
|
||||
}
|
||||
|
||||
inline void hyperscan_state::spg290_write_mem(UINT32 offset, UINT32 data)
|
||||
{
|
||||
return m_maincpu->space(0).write_dword(offset, data);
|
||||
}
|
||||
|
||||
void hyperscan_state::spg290_argb1555(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16 posy, UINT16 posx, UINT16 argb)
|
||||
{
|
||||
if (!(argb & 0x8000) && cliprect.contains(posx, posy))
|
||||
{
|
||||
rgb_t color = MAKE_RGB(pal5bit(argb >> 10), pal5bit(argb >> 5), pal5bit(argb >> 0));
|
||||
bitmap.pix32(posy, posx) = color;
|
||||
}
|
||||
}
|
||||
|
||||
void hyperscan_state::spg290_rgb565(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16 posy, UINT16 posx, UINT16 rgb, UINT32 transrgb)
|
||||
{
|
||||
if ((!(transrgb & 0x10000) || (transrgb & 0xffff) != rgb) && cliprect.contains(posx, posy))
|
||||
{
|
||||
rgb_t color = MAKE_RGB(pal5bit(rgb >> 11), pal6bit(rgb >> 5), pal5bit(rgb >> 0));
|
||||
bitmap.pix32(posy, posx) = color;
|
||||
}
|
||||
}
|
||||
|
||||
void hyperscan_state::spg290_blit_sprite(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT32 control, UINT32 attribute, UINT32 *palettes, UINT32 buf_start)
|
||||
{
|
||||
UINT32 sprite_base = buf_start + ((control & 0xffff) << 8);
|
||||
UINT16 sprite_x = (control >> 16) & 0x3ff;
|
||||
UINT16 sprite_y = (attribute >> 16) & 0x3ff;
|
||||
UINT8 sprite_hsize = 8 << ((attribute >> 4) & 0x03);
|
||||
UINT8 sprite_vsize = 8 << ((attribute >> 6) & 0x03);
|
||||
UINT8 bit_pixel = ((attribute & 3) + 1) << 1;
|
||||
UINT8 pixel_word = 32 / bit_pixel;
|
||||
UINT8 word_line = sprite_hsize / pixel_word;
|
||||
UINT8 sprite_flip = (attribute >> 2) & 0x03;
|
||||
|
||||
for (int y=0; y < sprite_vsize; y++)
|
||||
for (int x=0; x < word_line; x++)
|
||||
{
|
||||
UINT32 data = spg290_read_mem(sprite_base + (y * pixel_word + x) * 4);
|
||||
|
||||
for (int b=0; b < pixel_word; b++)
|
||||
{
|
||||
UINT16 pen = ((data >> (b * bit_pixel)) & ((1 << bit_pixel) - 1));
|
||||
UINT16 posx;
|
||||
if (sprite_flip & 0x01)
|
||||
posx = sprite_x + (sprite_hsize - (x * word_line + b));
|
||||
else
|
||||
posx = sprite_x + x * (word_line) + b;
|
||||
|
||||
UINT16 posy;
|
||||
if (sprite_flip & 0x02)
|
||||
posy = sprite_y + (sprite_vsize - y);
|
||||
else
|
||||
posy = sprite_y + y;
|
||||
|
||||
spg290_argb1555(bitmap, cliprect, posy, posx, palettes[pen]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hyperscan_state::spg290_blit_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT32 control, UINT32 attribute, int posy, int posx, UINT32 nptr, UINT32 buf_start, UINT32 transrgb)
|
||||
{
|
||||
for (int y=0; y<512; y++)
|
||||
{
|
||||
int line = (control & 0x04) ? 0 : y;
|
||||
UINT32 tx_start = spg290_read_mem(nptr + (posy + line) * 4);
|
||||
|
||||
for (int x=0; x < 1024>>1; x++)
|
||||
{
|
||||
UINT32 data = spg290_read_mem(buf_start + (tx_start + posx) * 2 + x * 4);
|
||||
|
||||
for (int b=0; b < 2; b++)
|
||||
{
|
||||
UINT16 posx = x * 2 + b;
|
||||
UINT16 posy = y;
|
||||
UINT16 pix = (data >> (b*16)) & 0xffff;
|
||||
|
||||
if (control & 0x0080)
|
||||
spg290_argb1555(bitmap, cliprect, posy, posx, pix);
|
||||
if (control & 0x1000)
|
||||
spg290_rgb565(bitmap, cliprect, posy, posx, pix, transrgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hyperscan_state::spg290_blit_character(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT32 control, UINT32 attribute, int posy, int posx, UINT32 nptr, UINT32 buf_start, UINT32 transrgb)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
UINT32 hyperscan_state::spg290_screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
if (m_ppu.control & 0x1000)
|
||||
{
|
||||
for (int depth=0; depth<4; depth++)
|
||||
{
|
||||
// draw the bitmap/text layers
|
||||
for (int l=0; l<3; l++)
|
||||
if ((m_ppu.txs[l].control & 0x08) && ((m_ppu.txs[l].attribute >> 13) & 3) == depth)
|
||||
{
|
||||
if (m_ppu.txs[l].control & 0x01)
|
||||
spg290_blit_bitmap(bitmap, cliprect, m_ppu.txs[l].control, m_ppu.txs[l].attribute, m_ppu.txs[l].posy & 0x1ff, m_ppu.txs[l].posx & 0x1ff, m_ppu.txs[l].nptr, m_ppu.txs[l].buf_start[0], m_ppu.transrgb);
|
||||
else
|
||||
spg290_blit_character(bitmap, cliprect, m_ppu.txs[l].control, m_ppu.txs[l].attribute, m_ppu.txs[l].posy & 0x1ff, m_ppu.txs[l].posx & 0x1ff, m_ppu.txs[l].nptr, m_ppu.txs[l].buf_start[0], m_ppu.transrgb);
|
||||
}
|
||||
|
||||
// draw the sprites
|
||||
for (int i=0; i<=(m_ppu.sprite_max & 0x1ff); i++)
|
||||
{
|
||||
if (((m_ppu.sprites[i].attribute >> 13) & 3) == depth)
|
||||
spg290_blit_sprite(bitmap, cliprect, m_ppu.sprites[i].control, m_ppu.sprites[i].attribute, m_ppu.palettes, m_ppu.sprite_buf_start);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap.fill(RGB_BLACK, cliprect);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hyperscan_state::spg290_timers_update()
|
||||
{
|
||||
for(int i=0; i<6; i++)
|
||||
if (m_timers[i].control & 0x80000000)
|
||||
{
|
||||
if (((m_timers[i].control2 >> 30) & 0x03) == 0x00)
|
||||
{
|
||||
if (m_timers[i].counter == 0xffff)
|
||||
{
|
||||
m_timers[i].counter = m_timers[i].preload;
|
||||
if (m_timers[i].control & 0x08000000)
|
||||
{
|
||||
m_timers[i].control |= 0x04000000;
|
||||
m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 56);
|
||||
}
|
||||
}
|
||||
else
|
||||
m_timers[i].counter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: capture, comparison and PWM mode
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hyperscan_state::spg290_vblank_irq(screen_device &screen, bool state)
|
||||
{
|
||||
if (state && m_ppu.irq_control & 0x01) // VBlanking Start IRQ
|
||||
{
|
||||
m_ppu.irq_status |= 0x01;
|
||||
m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 53);
|
||||
}
|
||||
else if (!state && m_ppu.irq_control & 0x02) // VBlanking End IRQ
|
||||
{
|
||||
m_ppu.irq_status |= 0x02;
|
||||
m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 53);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void hyperscan_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case TIMER_SPG290:
|
||||
spg290_timers_update();
|
||||
break;
|
||||
case TIMER_I2C:
|
||||
if ((m_i2c.config & 0x40) && (m_i2c.config & 0x01))
|
||||
{
|
||||
// TODO: replace with real I2C emulation
|
||||
m_i2c.rdata = 0;
|
||||
|
||||
m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 39);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static ADDRESS_MAP_START(spg290_mem, AS_PROGRAM, 32, hyperscan_state)
|
||||
ADDRESS_MAP_GLOBAL_MASK(0x1fffffff)
|
||||
AM_RANGE(0x00000000, 0x00ffffff) AM_RAM AM_MIRROR(0x07000000)
|
||||
AM_RANGE(0x08000000, 0x09ffffff) AM_READWRITE(spg290_regs_r, spg290_regs_w)
|
||||
AM_RANGE(0x0a000000, 0x0a003fff) AM_RAM // internal SRAM
|
||||
AM_RANGE(0x0b000000, 0x0b007fff) AM_ROM AM_REGION("spg290", 0) // internal ROM
|
||||
AM_RANGE(0x1e000000, 0x1e0fffff) AM_ROM AM_REGION("bios", 0) AM_MIRROR(0x0e000000)
|
||||
AM_RANGE(0x1f000000, 0x1f0fffff) AM_ROM AM_REGION("bios", 0) AM_MIRROR(0x0e000000)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
/* Input ports */
|
||||
static INPUT_PORTS_START( hyperscan )
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
void hyperscan_state::machine_start()
|
||||
{
|
||||
m_update_timer = timer_alloc(TIMER_SPG290);
|
||||
m_i2c_timer = timer_alloc(TIMER_I2C);
|
||||
}
|
||||
|
||||
void hyperscan_state::machine_reset()
|
||||
{
|
||||
memset(&m_ppu, 0, sizeof(spg290_ppu));
|
||||
memset(&m_miu, 0, sizeof(spg290_miu));
|
||||
memset(&m_i2c, 0, sizeof(m_i2c));
|
||||
m_i2c_timer->adjust(attotime::never, 0, attotime::never);
|
||||
|
||||
// disable JTAG
|
||||
m_maincpu->set_state_int(SCORE_CR + 29, 0x20000000);
|
||||
}
|
||||
|
||||
|
||||
static MACHINE_CONFIG_START( hyperscan, hyperscan_state )
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD("maincpu", SCORE7, XTAL_27MHz * 4) // 108MHz S+core 7
|
||||
MCFG_CPU_PROGRAM_MAP(spg290_mem)
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_REFRESH_RATE(50)
|
||||
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
|
||||
MCFG_SCREEN_UPDATE_DRIVER(hyperscan_state, spg290_screen_update)
|
||||
MCFG_SCREEN_SIZE(640, 480)
|
||||
MCFG_SCREEN_VISIBLE_AREA(0, 640-1, 0, 480-1)
|
||||
MCFG_SCREEN_VBLANK_DRIVER(hyperscan_state, spg290_vblank_irq)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
/* ROM definition */
|
||||
ROM_START( hs )
|
||||
ROM_REGION( 0x100000, "bios", ROMREGION_32BIT | ROMREGION_LE )
|
||||
ROM_LOAD32_DWORD("hyperscan.bin", 0x000000, 0x100000, CRC(ce346a14) SHA1(560cb747e7193e6781d4b8b0bd4d7b45d3d28690))
|
||||
|
||||
ROM_REGION( 0x008000, "spg290", ROMREGION_32BIT | ROMREGION_LE )
|
||||
ROM_LOAD32_DWORD("spg290.bin", 0x000000, 0x008000, NO_DUMP) // 256Kbit SPG290 internal ROM
|
||||
ROM_END
|
||||
|
||||
|
||||
/* Driver */
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
|
||||
COMP( 2006, hs, 0, 0, hyperscan , hyperscan , driver_device, 0, "Mattel", "HyperScan", GAME_NOT_WORKING | GAME_NO_SOUND)
|
@ -1421,6 +1421,7 @@ intvecs // 1983 - Mattel Intellivision ECS
|
||||
aquarius // 1983 Aquarius
|
||||
// aquariu2 // 1984 Aquarius II
|
||||
juicebox
|
||||
hs
|
||||
|
||||
// Exidy, Inc.
|
||||
sorcerer // Sorcerer
|
||||
|
@ -125,6 +125,7 @@ CPUS += PPS4
|
||||
CPUS += UPD7725
|
||||
CPUS += HD61700
|
||||
CPUS += LC8670
|
||||
CPUS += SCORE
|
||||
CPUS += ES5510
|
||||
CPUS += SCUDSP
|
||||
CPUS += IE15
|
||||
@ -1581,6 +1582,7 @@ $(MESSOBJ)/mattel.a: \
|
||||
$(MESS_VIDEO)/aquarius.o \
|
||||
$(MESS_DRIVERS)/juicebox.o \
|
||||
$(MESS_MACHINE)/s3c44b0.o \
|
||||
$(MESS_DRIVERS)/hyperscan.o \
|
||||
|
||||
$(MESSOBJ)/matsushi.a: \
|
||||
$(MESS_DRIVERS)/jr100.o \
|
||||
|
Loading…
Reference in New Issue
Block a user