cpu/z80: Revert a94254a while we figure out the severe performance regressions. [R. Belmont, holub]

This commit is contained in:
arbee 2023-08-30 14:11:14 -04:00
parent 39c569dc06
commit c06c4fd132
8 changed files with 2922 additions and 2636 deletions

View file

@ -206,7 +206,7 @@ bool kc82_device::memory_translate(int spacenum, int intention, offs_t &address,
// rm - read one byte from memory
//-------------------------------------------------
u8 kc82_device::data_read(u16 addr)
u8 kc82_device::rm(u16 addr)
{
return m_data.read_byte(addr + m_mmu_base[addr >> 10]);
}
@ -216,7 +216,7 @@ u8 kc82_device::data_read(u16 addr)
// wm - write one byte to memory
//-------------------------------------------------
void kc82_device::data_write(u16 addr, u8 value)
void kc82_device::wm(u16 addr, u8 value)
{
m_data.write_byte(addr + m_mmu_base[addr >> 10], value);
}
@ -226,9 +226,10 @@ void kc82_device::data_write(u16 addr, u8 value)
// rop - read opcode
//-------------------------------------------------
u8 kc82_device::opcode_read()
u8 kc82_device::rop()
{
u32 pc = m_pc.w.l + m_mmu_base[m_pc.b.h >> 2];
m_pc.w.l++;
// no refresh
return m_opcodes.read_byte(pc);
}
@ -238,8 +239,21 @@ u8 kc82_device::opcode_read()
// arg - read 8-bit argument
//-------------------------------------------------
u8 kc82_device::arg_read()
u8 kc82_device::arg()
{
u32 pc = m_pc.w.l + m_mmu_base[m_pc.b.h >> 2];
m_pc.w.l++;
return m_args.read_byte(pc);
}
//-------------------------------------------------
// arg16 - read 16-bit argument
//-------------------------------------------------
u16 kc82_device::arg16()
{
u16 d16 = arg();
d16 |= u16(arg()) << 8;
return d16;
}

View file

@ -41,10 +41,11 @@ protected:
virtual bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) override;
// z80_device overrides
virtual u8 data_read(u16 addr) override;
virtual void data_write(u16 addr, u8 value) override;
virtual u8 opcode_read() override;
virtual u8 arg_read() override;
virtual u8 rm(u16 addr) override;
virtual void wm(u16 addr, u8 value) override;
virtual u8 rop() override;
virtual u8 arg() override;
virtual u16 arg16() override;
// MMU access
u8 mmu_r(offs_t offset);

File diff suppressed because it is too large Load diff

View file

@ -13,7 +13,7 @@ enum
NSC800_RSTB,
NSC800_RSTC,
Z80_INPUT_LINE_WAIT,
Z80_INPUT_LINE_BOGUSWAIT, // WAIT pin implementation used to be nonexistent, please remove this when all drivers are updated with Z80_INPUT_LINE_WAIT
Z80_INPUT_LINE_BOGUSWAIT, /* WAIT pin implementation used to be nonexistent, please remove this when all drivers are updated with Z80_INPUT_LINE_WAIT */
Z80_INPUT_LINE_BUSRQ
};
@ -30,11 +30,10 @@ enum
class z80_device : public cpu_device, public z80_daisy_chain_interface
{
public:
z80_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
z80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void z80_set_m1_cycles(u8 m1_cycles) { m_m1_cycles = m1_cycles; }
void z80_set_memrq_cycles(u8 memrq_cycles) { m_memrq_cycles = memrq_cycles; }
void z80_set_iorq_cycles(u8 iorq_cycles) { m_iorq_cycles = iorq_cycles; }
void z80_set_cycle_tables(const uint8_t *op, const uint8_t *cb, const uint8_t *ed, const uint8_t *xy, const uint8_t *xycb, const uint8_t *ex);
void set_mtm_cycles(uint8_t mtm_cycles);
template <typename... T> void set_memory_map(T &&... args) { set_addrmap(AS_PROGRAM, std::forward<T>(args)...); }
template <typename... T> void set_m1_map(T &&... args) { set_addrmap(AS_OPCODES, std::forward<T>(args)...); }
template <typename... T> void set_io_map(T &&... args) { set_addrmap(AS_IO, std::forward<T>(args)...); }
@ -44,91 +43,17 @@ public:
auto halt_cb() { return m_halt_cb.bind(); }
protected:
using ops_type = std::vector<std::function<void()>>;
enum op_prefix : u8
{
NONE = 0, CB, DD, ED, FD, XY_CB
};
class op_builder
{
public:
op_builder (z80_device& z80) : m_z80(z80) {};
ops_type get_steps() { return m_steps; }
op_builder * foo(std::function<void()> step) { return this; } // discards content. needed to make macros balanced
op_builder * add(ops_type steps)
{
assert(!steps.empty());
auto to = m_if_condition == nullptr ? &m_steps : &m_if_steps;
to->insert(to->end(), steps.begin(), steps.end());
return this;
}
op_builder * add(std::function<void()> step)
{
auto to = m_if_condition == nullptr ? &m_steps : &m_if_steps;
to->push_back(step);
return this;
}
op_builder * call(std::function<ops_type()> steps) { return add(steps()); }
op_builder * do_if(std::function<bool()> if_condition) { m_if_condition = if_condition; return this; }
op_builder * do_else() { assert(!m_if_steps.empty()); m_else_at = m_if_steps.size(); return this; }
op_builder * edo()
{
assert(!m_if_steps.empty());
auto cond = m_if_condition;
m_if_condition = nullptr;
z80_device& z80 = m_z80;
if (m_else_at)
{
auto steps = m_else_at + 1;
add([&z80, steps, cond](){ if (!cond()) { z80.m_cycle += steps; }});
add({m_if_steps.begin(), m_if_steps.begin() + m_else_at});
steps = m_if_steps.size() - m_else_at;
add([&z80, steps](){ z80.m_cycle += steps; });
add({m_if_steps.begin() + m_else_at, m_if_steps.end()});
m_else_at = 0;
}
else
{
auto steps = m_if_steps.size();
add([&z80, steps, cond](){ if (!cond()) { z80.m_cycle += steps; }});
add(m_if_steps);
}
m_if_steps.clear();
return this;
}
ops_type jump(op_prefix prefix, u8 opcode)
{
z80_device& z80 = m_z80;
add([&z80, prefix, opcode](){ z80.m_cycle = ~0; z80.m_prefix = prefix; z80.m_opcode = opcode; });
return m_steps;
}
ops_type jump(u8 opcode) { return jump(NONE, opcode); }
ops_type build() { add(m_z80.next_op()); return m_steps; }
private:
z80_device& m_z80;
ops_type m_steps;
std::function<bool()> m_if_condition = nullptr;
ops_type m_if_steps;
u8 m_else_at = 0;
};
z80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
z80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
void init_op_steps();
// device_execute_interface overrides
virtual bool cpu_is_interruptible() const override { return true; }
virtual u32 execute_min_cycles() const noexcept override { return 2; }
virtual u32 execute_max_cycles() const noexcept override { return 16; }
virtual u32 execute_input_lines() const noexcept override { return 4; }
virtual u32 execute_default_irq_vector(int inputnum) const noexcept override { return 0xff; }
virtual uint32_t execute_min_cycles() const noexcept override { return 2; }
virtual uint32_t execute_max_cycles() const noexcept override { return 16; }
virtual uint32_t execute_input_lines() const noexcept override { return 4; }
virtual uint32_t execute_default_irq_vector(int inputnum) const noexcept override { return 0xff; }
virtual bool execute_input_edge_triggered(int inputnum) const noexcept override { return inputnum == INPUT_LINE_NMI; }
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override;
@ -145,112 +70,175 @@ protected:
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
void execute_cycles(u8 icount);
void halt();
void leave_halt();
virtual u8 data_read(u16 addr);
virtual void data_write(u16 addr, u8 value);
virtual u8 opcode_read();
virtual u8 arg_read();
/* deprecated */ void rm16(u16 addr, PAIR &r);
/* deprecated */ void wm16_sp(PAIR &r);
#undef PROTOTYPES
#define PROTOTYPES(prefix) \
void prefix##_00(); void prefix##_01(); void prefix##_02(); void prefix##_03(); \
void prefix##_04(); void prefix##_05(); void prefix##_06(); void prefix##_07(); \
void prefix##_08(); void prefix##_09(); void prefix##_0a(); void prefix##_0b(); \
void prefix##_0c(); void prefix##_0d(); void prefix##_0e(); void prefix##_0f(); \
void prefix##_10(); void prefix##_11(); void prefix##_12(); void prefix##_13(); \
void prefix##_14(); void prefix##_15(); void prefix##_16(); void prefix##_17(); \
void prefix##_18(); void prefix##_19(); void prefix##_1a(); void prefix##_1b(); \
void prefix##_1c(); void prefix##_1d(); void prefix##_1e(); void prefix##_1f(); \
void prefix##_20(); void prefix##_21(); void prefix##_22(); void prefix##_23(); \
void prefix##_24(); void prefix##_25(); void prefix##_26(); void prefix##_27(); \
void prefix##_28(); void prefix##_29(); void prefix##_2a(); void prefix##_2b(); \
void prefix##_2c(); void prefix##_2d(); void prefix##_2e(); void prefix##_2f(); \
void prefix##_30(); void prefix##_31(); void prefix##_32(); void prefix##_33(); \
void prefix##_34(); void prefix##_35(); void prefix##_36(); void prefix##_37(); \
void prefix##_38(); void prefix##_39(); void prefix##_3a(); void prefix##_3b(); \
void prefix##_3c(); void prefix##_3d(); void prefix##_3e(); void prefix##_3f(); \
void prefix##_40(); void prefix##_41(); void prefix##_42(); void prefix##_43(); \
void prefix##_44(); void prefix##_45(); void prefix##_46(); void prefix##_47(); \
void prefix##_48(); void prefix##_49(); void prefix##_4a(); void prefix##_4b(); \
void prefix##_4c(); void prefix##_4d(); void prefix##_4e(); void prefix##_4f(); \
void prefix##_50(); void prefix##_51(); void prefix##_52(); void prefix##_53(); \
void prefix##_54(); void prefix##_55(); void prefix##_56(); void prefix##_57(); \
void prefix##_58(); void prefix##_59(); void prefix##_5a(); void prefix##_5b(); \
void prefix##_5c(); void prefix##_5d(); void prefix##_5e(); void prefix##_5f(); \
void prefix##_60(); void prefix##_61(); void prefix##_62(); void prefix##_63(); \
void prefix##_64(); void prefix##_65(); void prefix##_66(); void prefix##_67(); \
void prefix##_68(); void prefix##_69(); void prefix##_6a(); void prefix##_6b(); \
void prefix##_6c(); void prefix##_6d(); void prefix##_6e(); void prefix##_6f(); \
void prefix##_70(); void prefix##_71(); void prefix##_72(); void prefix##_73(); \
void prefix##_74(); void prefix##_75(); void prefix##_76(); void prefix##_77(); \
void prefix##_78(); void prefix##_79(); void prefix##_7a(); void prefix##_7b(); \
void prefix##_7c(); void prefix##_7d(); void prefix##_7e(); void prefix##_7f(); \
void prefix##_80(); void prefix##_81(); void prefix##_82(); void prefix##_83(); \
void prefix##_84(); void prefix##_85(); void prefix##_86(); void prefix##_87(); \
void prefix##_88(); void prefix##_89(); void prefix##_8a(); void prefix##_8b(); \
void prefix##_8c(); void prefix##_8d(); void prefix##_8e(); void prefix##_8f(); \
void prefix##_90(); void prefix##_91(); void prefix##_92(); void prefix##_93(); \
void prefix##_94(); void prefix##_95(); void prefix##_96(); void prefix##_97(); \
void prefix##_98(); void prefix##_99(); void prefix##_9a(); void prefix##_9b(); \
void prefix##_9c(); void prefix##_9d(); void prefix##_9e(); void prefix##_9f(); \
void prefix##_a0(); void prefix##_a1(); void prefix##_a2(); void prefix##_a3(); \
void prefix##_a4(); void prefix##_a5(); void prefix##_a6(); void prefix##_a7(); \
void prefix##_a8(); void prefix##_a9(); void prefix##_aa(); void prefix##_ab(); \
void prefix##_ac(); void prefix##_ad(); void prefix##_ae(); void prefix##_af(); \
void prefix##_b0(); void prefix##_b1(); void prefix##_b2(); void prefix##_b3(); \
void prefix##_b4(); void prefix##_b5(); void prefix##_b6(); void prefix##_b7(); \
void prefix##_b8(); void prefix##_b9(); void prefix##_ba(); void prefix##_bb(); \
void prefix##_bc(); void prefix##_bd(); void prefix##_be(); void prefix##_bf(); \
void prefix##_c0(); void prefix##_c1(); void prefix##_c2(); void prefix##_c3(); \
void prefix##_c4(); void prefix##_c5(); void prefix##_c6(); void prefix##_c7(); \
void prefix##_c8(); void prefix##_c9(); void prefix##_ca(); void prefix##_cb(); \
void prefix##_cc(); void prefix##_cd(); void prefix##_ce(); void prefix##_cf(); \
void prefix##_d0(); void prefix##_d1(); void prefix##_d2(); void prefix##_d3(); \
void prefix##_d4(); void prefix##_d5(); void prefix##_d6(); void prefix##_d7(); \
void prefix##_d8(); void prefix##_d9(); void prefix##_da(); void prefix##_db(); \
void prefix##_dc(); void prefix##_dd(); void prefix##_de(); void prefix##_df(); \
void prefix##_e0(); void prefix##_e1(); void prefix##_e2(); void prefix##_e3(); \
void prefix##_e4(); void prefix##_e5(); void prefix##_e6(); void prefix##_e7(); \
void prefix##_e8(); void prefix##_e9(); void prefix##_ea(); void prefix##_eb(); \
void prefix##_ec(); void prefix##_ed(); void prefix##_ee(); void prefix##_ef(); \
void prefix##_f0(); void prefix##_f1(); void prefix##_f2(); void prefix##_f3(); \
void prefix##_f4(); void prefix##_f5(); void prefix##_f6(); void prefix##_f7(); \
void prefix##_f8(); void prefix##_f9(); void prefix##_fa(); void prefix##_fb(); \
void prefix##_fc(); void prefix##_fd(); void prefix##_fe(); void prefix##_ff();
void illegal_1();
void illegal_2();
ops_type in();
ops_type out();
ops_type rm();
ops_type rm_reg();
ops_type rm16();
ops_type wm();
ops_type wm16();
ops_type wm16_sp();
ops_type rop();
ops_type arg();
ops_type arg16();
ops_type eax();
ops_type eay();
ops_type push();
ops_type pop();
ops_type jp();
ops_type jp_cond();
ops_type jr();
ops_type jr_cond(u8 opcode);
ops_type call();
ops_type call_cond(u8 opcode);
ops_type ret_cond(u8 opcode);
ops_type retn();
ops_type reti();
ops_type ld_r_a();
ops_type ld_a_r();
ops_type ld_i_a();
ops_type ld_a_i();
ops_type rst(u16 addr);
void inc(u8 &r);
void dec(u8 &r);
PROTOTYPES(op)
PROTOTYPES(cb)
PROTOTYPES(dd)
PROTOTYPES(ed)
PROTOTYPES(fd)
PROTOTYPES(xycb)
void halt();
void leave_halt();
uint8_t in(uint16_t port);
void out(uint16_t port, uint8_t value);
virtual uint8_t rm(uint16_t addr);
uint8_t rm_reg(uint16_t addr);
void rm16(uint16_t addr, PAIR &r);
virtual void wm(uint16_t addr, uint8_t value);
void wm16(uint16_t addr, PAIR &r);
void wm16_sp(PAIR &r);
virtual uint8_t rop();
virtual uint8_t arg();
virtual uint16_t arg16();
void eax();
void eay();
void pop(PAIR &r);
void push(PAIR &r);
void jp(void);
void jp_cond(bool cond);
void jr();
void jr_cond(bool cond, uint8_t opcode);
void call();
void call_cond(bool cond, uint8_t opcode);
void ret_cond(bool cond, uint8_t opcode);
void retn();
void reti();
void ld_r_a();
void ld_a_r();
void ld_i_a();
void ld_a_i();
void rst(uint16_t addr);
uint8_t inc(uint8_t value);
uint8_t dec(uint8_t value);
void rlca();
void rrca();
void rla();
void rra();
ops_type rrd();
ops_type rld();
void add_a(u8 value);
void adc_a(u8 value);
void sub(u8 value);
void sbc_a(u8 value);
void rrd();
void rld();
void add_a(uint8_t value);
void adc_a(uint8_t value);
void sub(uint8_t value);
void sbc_a(uint8_t value);
void neg();
void daa();
void and_a(u8 value);
void or_a(u8 value);
void xor_a(u8 value);
void cp(u8 value);
void and_a(uint8_t value);
void or_a(uint8_t value);
void xor_a(uint8_t value);
void cp(uint8_t value);
void ex_af();
void ex_de_hl();
void exx();
ops_type ex_sp();
ops_type add16();
ops_type adc_hl();
ops_type sbc_hl();
u8 rlc(u8 value);
u8 rrc(u8 value);
u8 rl(u8 value);
u8 rr(u8 value);
u8 sla(u8 value);
u8 sra(u8 value);
u8 sll(u8 value);
u8 srl(u8 value);
void bit(int bit, u8 value);
void bit_hl(int bit, u8 value);
void bit_xy(int bit, u8 value);
u8 res(int bit, u8 value);
u8 set(int bit, u8 value);
ops_type ldi();
ops_type cpi();
ops_type ini();
ops_type outi();
ops_type ldd();
ops_type cpd();
ops_type ind();
ops_type outd();
ops_type ldir();
ops_type cpir();
ops_type inir();
ops_type otir();
ops_type lddr();
ops_type cpdr();
ops_type indr();
ops_type otdr();
void ex_sp(PAIR &r);
void add16(PAIR &dr, PAIR &sr);
void adc_hl(PAIR &r);
void sbc_hl(PAIR &r);
uint8_t rlc(uint8_t value);
uint8_t rrc(uint8_t value);
uint8_t rl(uint8_t value);
uint8_t rr(uint8_t value);
uint8_t sla(uint8_t value);
uint8_t sra(uint8_t value);
uint8_t sll(uint8_t value);
uint8_t srl(uint8_t value);
void bit(int bit, uint8_t value);
void bit_hl(int bit, uint8_t value);
void bit_xy(int bit, uint8_t value);
uint8_t res(int bit, uint8_t value);
uint8_t set(int bit, uint8_t value);
void ldi();
void cpi();
void ini();
void outi();
void ldd();
void cpd();
void ind();
void outd();
void ldir();
void cpir();
void inir();
void otir();
void lddr();
void cpdr();
void indr();
void otdr();
void ei();
void set_f(u8 f);
void block_io_interrupted_flags();
ops_type next_op();
virtual void check_interrupts();
void take_interrupt();
void take_nmi();
ops_type nomreq_ir(s8 cycles);
ops_type nomreq_addr(s8 cycles);
void nomreq_ir(s8 cycles);
void nomreq_addr(u16 addr, s8 cycles);
// address spaces
const address_space_config m_program_config;
@ -280,38 +268,32 @@ protected:
PAIR m_bc2;
PAIR m_de2;
PAIR m_hl2;
u8 m_qtemp;
u8 m_q;
u8 m_r;
u8 m_r2;
u8 m_iff1;
u8 m_iff2;
u8 m_halt;
u8 m_im;
u8 m_i;
u8 m_nmi_state; // nmi line state
u8 m_nmi_pending; // nmi pending
u8 m_irq_state; // irq line state
uint8_t m_r;
uint8_t m_r2;
uint8_t m_iff1;
uint8_t m_iff2;
uint8_t m_halt;
uint8_t m_im;
uint8_t m_i;
uint8_t m_nmi_state; /* nmi line state */
uint8_t m_nmi_pending; /* nmi pending */
uint8_t m_irq_state; /* irq line state */
int m_wait_state; // wait line state
int m_busrq_state; // bus request line state
u8 m_after_ei; // are we in the EI shadow?
u8 m_after_ldair; // same, but for LD A,I or LD A,R
u32 m_ea;
uint8_t m_after_ei; /* are we in the EI shadow? */
uint8_t m_after_ldair; /* same, but for LD A,I or LD A,R */
uint32_t m_ea;
u8 m_cycle;
op_prefix m_prefix;
u8 m_opcode;
int m_icount;
PAIR16 m_m_shared_addr;
PAIR16 m_m_shared_data;
PAIR16 m_m_shared_data2;
u8 m_rtemp;
ops_type m_op_steps[6][0x100];
u8 m_m1_cycles = 4;
u8 m_memrq_cycles = 3;
u8 m_iorq_cycles = 4;
int m_icount_executing;
uint8_t m_rtemp;
const uint8_t * m_cc_op;
const uint8_t * m_cc_cb;
const uint8_t * m_cc_ed;
const uint8_t * m_cc_xy;
const uint8_t * m_cc_xycb;
const uint8_t * m_cc_ex;
uint8_t m_mtm_cycles;
};
DECLARE_DEVICE_TYPE(Z80, z80_device)
@ -319,7 +301,7 @@ DECLARE_DEVICE_TYPE(Z80, z80_device)
class nsc800_device : public z80_device
{
public:
nsc800_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
nsc800_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
@ -327,12 +309,12 @@ protected:
virtual void device_reset() override;
// device_execute_interface overrides
virtual u32 execute_input_lines() const noexcept override { return 7; }
virtual uint32_t execute_input_lines() const noexcept override { return 7; }
virtual void execute_set_input(int inputnum, int state) override;
virtual void check_interrupts() override;
void take_interrupt_nsc800();
u8 m_nsc800_irq_state[4]; // state of NSC800 restart interrupts A, B, C
uint8_t m_nsc800_irq_state[4]; /* state of NSC800 restart interrupts A, B, C */
};
DECLARE_DEVICE_TYPE(NSC800, nsc800_device)

View file

@ -93,10 +93,10 @@ Some bugs left :
#include "amstrad.h"
/* Components */
#include "machine/i8255.h" /* for 8255 ppi */
#include "cpu/z80/z80.h" /* for cycle tables */
#include "video/mc6845.h" /* CRTC */
#include "machine/upd765.h" /* for floppy disc controller */
#include "machine/i8255.h" /* for 8255 ppi */
#include "cpu/z80/z80.h" /* for cycle tables */
#include "video/mc6845.h" /* CRTC */
#include "machine/upd765.h" /* for floppy disc controller */
#include "sound/ay8910.h"
#include "machine/mc146818.h" /* Aleste RTC */
#include "bus/centronics/ctronics.h"
@ -121,11 +121,19 @@ Some bugs left :
#define SYSTEM_GX4000 2
/* Memory is banked in 16k blocks. However, the multiface pages the memory in 8k blocks!
The ROM can be paged into bank 0 and bank 3. */
/* Memory is banked in 16k blocks. However, the multiface
pages the memory in 8k blocks! The ROM can
be paged into bank 0 and bank 3. */
void amstrad_state::amstrad_mem(address_map &map)
{
map(0x0000, 0xffff).rw(FUNC(amstrad_state::amstrad_cpc_mem_r), FUNC(amstrad_state::amstrad_cpc_mem_w));
map(0x00000, 0x01fff).bankr("bank1").bankw("bank9");
map(0x02000, 0x03fff).bankr("bank2").bankw("bank10");
map(0x04000, 0x05fff).bankr("bank3").bankw("bank11");
map(0x06000, 0x07fff).bankr("bank4").bankw("bank12");
map(0x08000, 0x09fff).bankr("bank5").bankw("bank13");
map(0x0a000, 0x0bfff).bankr("bank6").bankw("bank14");
map(0x0c000, 0x0dfff).bankr("bank7").bankw("bank15");
map(0x0e000, 0x0ffff).bankr("bank8").bankw("bank16");
}
/* I've handled the I/O ports in this way, because the ports
@ -145,9 +153,9 @@ void amstrad_state::amstrad_io(address_map &map)
static INPUT_PORTS_START( amstrad_keyboard )
PORT_START("kbrow.0")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 9") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
@ -155,7 +163,7 @@ static INPUT_PORTS_START( amstrad_keyboard )
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad .") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
PORT_START("kbrow.1")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Copy") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(END))
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 7") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 8") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
@ -335,8 +343,8 @@ static INPUT_PORTS_START( amx_mouse )
PORT_BIT(0xff , 0, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_PLAYER(1) PORT_CONDITION("controller_type", 0x02, EQUALS, 0x02)
PORT_START("mouse_input3")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_NAME("Left mouse button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CONDITION("controller_type", 0x02, EQUALS, 0x02)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("Right mouse button") PORT_CODE(MOUSECODE_BUTTON2) PORT_CONDITION("controller_type", 0x02, EQUALS, 0x02)
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_NAME("Left mouse button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CONDITION("controller_type", 0x02, EQUALS, 0x02)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("Right mouse button") PORT_CODE(MOUSECODE_BUTTON2) PORT_CONDITION("controller_type", 0x02, EQUALS, 0x02)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON6) PORT_NAME("Middle mouse button") PORT_CODE(MOUSECODE_BUTTON3) PORT_CONDITION("controller_type", 0x02, EQUALS, 0x02)
PORT_START("controller_type")
@ -1192,7 +1200,8 @@ void amstrad_state::aleste(machine_config &config)
/* cpc6128.rom contains OS in first 16k, BASIC in second 16k */
/* cpcados.rom contains Amstrad DOS */
/* I am loading the roms outside of the Z80 memory area, because they are banked. */
/* I am loading the roms outside of the Z80 memory area, because they
are banked. */
ROM_START( cpc6128 )
/* this defines the total memory size - 64k ram, 16k OS, 16k BASIC, 16k DOS */
ROM_REGION(0x020000, "maincpu", 0)
@ -1203,7 +1212,7 @@ ROM_END
ROM_START( cpc6128f )
/* this defines the total memory size (128kb))- 64k ram, 16k OS, 16k BASIC, 16k DOS +16k */
/* this defines the total memory size (128kb))- 64k ram, 16k OS, 16k BASIC, 16k DOS +16k*/
ROM_REGION(0x020000, "maincpu", 0)
/* load the os to offset 0x01000 from memory base */
@ -1213,7 +1222,7 @@ ROM_END
ROM_START( cpc6128s )
/* this defines the total memory size (128kb))- 64k ram, 16k OS, 16k BASIC, 16k DOS +16k */
/* this defines the total memory size (128kb))- 64k ram, 16k OS, 16k BASIC, 16k DOS +16k*/
ROM_REGION(0x020000, "maincpu", 0)
/* load the os to offset 0x01000 from memory base */
@ -1222,7 +1231,7 @@ ROM_START( cpc6128s )
ROM_END
ROM_START( cpc6128sp )
/* this defines the total memory size (128kb))- 64k ram, 16k OS, 16k BASIC, 16k DOS +16k */
/* this defines the total memory size (128kb))- 64k ram, 16k OS, 16k BASIC, 16k DOS +16k*/
ROM_REGION(0x020000, "maincpu", 0)
/* load the os to offset 0x01000 from memory base */
@ -1300,16 +1309,15 @@ ROM_END
*
*************************************/
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
COMP( 1984, cpc464, 0, 0, cpc464, cpc464, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC464", 0 )
COMP( 1985, cpc664, cpc464, 0, cpc664, cpc664, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC664", 0 )
COMP( 1985, cpc6128, cpc464, 0, cpc6128, cpc6128, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC6128", 0 )
COMP( 1985, cpc6128f, cpc464, 0, cpc6128, cpc6128f, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC6128 (France, AZERTY Keyboard)", 0 )
COMP( 1985, cpc6128s, cpc464, 0, cpc6128, cpc6128s, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC6128 (Sweden/Finland)", 0 )
COMP( 1985, cpc6128sp, cpc464, 0, cpc6128, cpc6128sp, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC6128 (Spain)", 0 )
COMP( 1990, cpc464p, 0, 0, cpcplus, plus, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC464+", 0 )
COMP( 1990, cpc6128p, 0, 0, cpcplus, plus, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC6128+", 0 )
CONS( 1990, gx4000, 0, 0, gx4000, gx4000, amstrad_state, empty_init, "Amstrad plc", "Amstrad GX4000", 0 )
COMP( 1989, kccomp, cpc464, 0, kccomp, kccomp, amstrad_state, empty_init, u8"VEB Mikroelektronik \"Wilhelm Pieck\" Mühlhausen",
"KC Compact", 0 )
COMP( 1993, al520ex, cpc464, 0, aleste, aleste, amstrad_state, empty_init, "Patisonic", "Aleste 520EX", MACHINE_IMPERFECT_SOUND )
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
COMP( 1984, cpc464, 0, 0, cpc464, cpc464, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC464", 0 )
COMP( 1985, cpc664, cpc464, 0, cpc664, cpc664, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC664", 0 )
COMP( 1985, cpc6128, cpc464, 0, cpc6128, cpc6128, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC6128", 0 )
COMP( 1985, cpc6128f, cpc464, 0, cpc6128, cpc6128f, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC6128 (France, AZERTY Keyboard)", 0 )
COMP( 1985, cpc6128s, cpc464, 0, cpc6128, cpc6128s, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC6128 (Sweden/Finland)", 0 )
COMP( 1985, cpc6128sp, cpc464, 0, cpc6128, cpc6128sp, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC6128 (Spain)", 0 )
COMP( 1990, cpc464p, 0, 0, cpcplus, plus, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC464+", 0 )
COMP( 1990, cpc6128p, 0, 0, cpcplus, plus, amstrad_state, empty_init, "Amstrad plc", "Amstrad CPC6128+", 0 )
CONS( 1990, gx4000, 0, 0, gx4000, gx4000, amstrad_state, empty_init, "Amstrad plc", "Amstrad GX4000", 0 )
COMP( 1989, kccomp, cpc464, 0, kccomp, kccomp, amstrad_state, empty_init, u8"VEB Mikroelektronik \"Wilhelm Pieck\" Mühlhausen", "KC Compact", 0 )
COMP( 1993, al520ex, cpc464, 0, aleste, aleste, amstrad_state, empty_init, "Patisonic", "Aleste 520EX", MACHINE_IMPERFECT_SOUND )

View file

@ -211,8 +211,6 @@ private:
void aleste_msx_mapper(offs_t offset, uint8_t data);
uint8_t amstrad_cpc_io_r(offs_t offset);
void amstrad_cpc_io_w(offs_t offset, uint8_t data);
uint8_t amstrad_cpc_mem_r(offs_t offset);
void amstrad_cpc_mem_w(offs_t offset, uint8_t data);
uint8_t amstrad_psg_porta_read();
void amstrad_plus_seqcheck(int data);
DECLARE_MACHINE_START(amstrad);
@ -268,7 +266,7 @@ private:
required_memory_region m_region_maincpu;
optional_memory_region m_region_user1;
memory_bank_array_creator<16> m_banks;
required_memory_bank_array<16> m_banks;
optional_ioport_array<11> m_io_kbrow;
optional_ioport_array<4> m_io_analog;
optional_ioport_array<3> m_io_mouse;

View file

@ -31,14 +31,8 @@ the name I give to the time taken for one NOP command to execute.
This happens to be 1us.
Timings:
From measurement, there are 64 NOPs per line, with 312 lines per screen. This
gives a total of 19968 NOPs per frame.
The Amstrad hardware issues a HALT for each memory fetch. This has the effect
of stretching the timing for Z80 opcodes, so that they are all multiple of 4 T
states long. All opcode timings are a multiple of 1us in length.
From measurement, there are 64 NOPs per line, with 312 lines per screen.
This gives a total of 19968 NOPs per frame.
***************************************************************************/
@ -103,14 +97,14 @@ static const uint8_t asic_unlock_seq[15] =
The following tables show the possible ram configurations :*/
static const int RamConfigurations[8 * 4] =
{
0, 1, 2, 3, /* config 0 */
0, 1, 2, 7, /* config 1 */
4, 5, 6, 7, /* config 2 */
0, 3, 2, 7, /* config 3 */
0, 4, 2, 3, /* config 4 */
0, 5, 2, 3, /* config 5 */
0, 6, 2, 3, /* config 6 */
0, 7, 2, 3 /* config 7 */
0, 1, 2, 3, /* config 0 */
0, 1, 2, 7, /* config 1 */
4, 5, 6, 7, /* config 2 */
0, 3, 2, 7, /* config 3 */
0, 4, 2, 3, /* config 4 */
0, 5, 2, 3, /* config 5 */
0, 6, 2, 3, /* config 6 */
0, 7, 2, 3 /* config 7 */
};
@ -171,32 +165,32 @@ static const rgb_t amstrad_green_palette[32] =
rgb_t(0x000, 0x07F, 0x000), /*13*/
rgb_t(0x000, 0x0BA, 0x000), /*19*/
rgb_t(0x000, 0x0F5, 0x000), /*25*/
rgb_t(0x000, 0x009, 0x000), /* 1*/
rgb_t(0x000, 0x044, 0x000), /* 7*/
rgb_t(0x000, 0x009, 0x000), /*1*/
rgb_t(0x000, 0x044, 0x000), /*7*/
rgb_t(0x000, 0x062, 0x000), /*10*/
rgb_t(0x000, 0x09C, 0x000), /*16*/
rgb_t(0x000, 0x044, 0x000), /* 7*/
rgb_t(0x000, 0x044, 0x000), /*7*/
rgb_t(0x000, 0x0F5, 0x000), /*25*/
rgb_t(0x000, 0x0EB, 0x000), /*24*/
rgb_t(0x000, 0x0FF, 0x000), /*26*/
rgb_t(0x000, 0x03A, 0x000), /* 6*/
rgb_t(0x000, 0x04E, 0x000), /* 8*/
rgb_t(0x000, 0x03A, 0x000), /*6*/
rgb_t(0x000, 0x04E, 0x000), /*8*/
rgb_t(0x000, 0x093, 0x000), /*15*/
rgb_t(0x000, 0x0A6, 0x000), /*17*/
rgb_t(0x000, 0x009, 0x000), /* 1*/
rgb_t(0x000, 0x009, 0x000), /*1*/
rgb_t(0x000, 0x0BA, 0x000), /*19*/
rgb_t(0x000, 0x0B0, 0x000), /*18*/
rgb_t(0x000, 0x0C4, 0x000), /*20*/
rgb_t(0x000, 0x000, 0x000), /* 0*/
rgb_t(0x000, 0x013, 0x000), /* 2*/
rgb_t(0x000, 0x058, 0x000), /* 9*/
rgb_t(0x000, 0x000, 0x000), /*0*/
rgb_t(0x000, 0x013, 0x000), /*2*/
rgb_t(0x000, 0x058, 0x000), /*9*/
rgb_t(0x000, 0x06B, 0x000), /*11*/
rgb_t(0x000, 0x027, 0x000), /* 4*/
rgb_t(0x000, 0x027, 0x000), /*4*/
rgb_t(0x000, 0x0D7, 0x000), /*22*/
rgb_t(0x000, 0x0CD, 0x000), /*21*/
rgb_t(0x000, 0x0E1, 0x000), /*23*/
rgb_t(0x000, 0x01D, 0x000), /* 3*/
rgb_t(0x000, 0x031, 0x000), /* 5*/
rgb_t(0x000, 0x01D, 0x000), /*3*/
rgb_t(0x000, 0x031, 0x000), /*5*/
rgb_t(0x000, 0x075, 0x000), /*12*/
rgb_t(0x000, 0x089, 0x000) /*14*/
};
@ -2180,18 +2174,6 @@ The exception is the case where none of b7-b0 are reset (i.e. port &FBFF), which
}
}
uint8_t amstrad_state::amstrad_cpc_mem_r(offs_t offset)
{
if (!machine().side_effects_disabled())
m_maincpu->adjust_icount(-((4 - m_maincpu->total_cycles() % 4) % 4));
return ((u8*)m_banks[(offset >> 13)]->base())[offset & 0x1fff];
}
void amstrad_state::amstrad_cpc_mem_w(offs_t offset, uint8_t data)
{
m_maincpu->adjust_icount(-((4 - m_maincpu->total_cycles() % 4) % 4));
((u8*)m_banks[(offset >> 13) + 8]->base())[offset & 0x1fff] = data;
}
/* load CPCEMU style snapshots */
void amstrad_state::amstrad_handle_snapshot(unsigned char *pSnapshot)
@ -2784,6 +2766,125 @@ IRQ_CALLBACK_MEMBER(amstrad_state::amstrad_cpu_acknowledge_int)
}
/* the following timings have been measured! */
static const uint8_t amstrad_cycle_table_op[256] = {
4, 12, 8, 8, 4, 4, 8, 4, 4, 12, 8, 8, 4, 4, 8, 4,
12, 12, 8, 8, 4, 4, 8, 4, 12, 12, 8, 8, 4, 4, 8, 4,
8, 12, 20, 8, 4, 4, 8, 4, 8, 12, 20, 8, 4, 4, 8, 4,
8, 12, 16, 8, 12, 12, 12, 4, 8, 12, 16, 8, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
8, 8, 8, 8, 8, 8, 4, 8, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
8, 12, 12, 12, 12, 16, 8, 16, 8, 12, 12, 4, 12, 20, 8, 16,
8, 12, 12, 12, 12, 16, 8, 16, 8, 4, 12, 12, 12, 4, 8, 16,
8, 12, 12, 24, 12, 16, 8, 16, 8, 4, 12, 4, 12, 4, 8, 16,
8, 12, 12, 4, 12, 16, 8, 16, 8, 8, 12, 4, 12, 4, 8, 16
};
static const uint8_t amstrad_cycle_table_cb[256]=
{
4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 4, 4, 12, 4,
4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 4, 4, 12, 4,
4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 4, 4, 12, 4,
4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 4, 4, 12, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 4, 4, 12, 4,
4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 4, 4, 12, 4,
4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 4, 4, 12, 4,
4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 4, 4, 12, 4,
4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 4, 4, 12, 4,
4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 4, 4, 12, 4,
4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 4, 4, 12, 4,
4, 4, 4, 4, 4, 4, 12, 4, 4, 4, 4, 4, 4, 4, 12, 4
};
static const uint8_t amstrad_cycle_table_ed[256]=
{
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
12, 12, 12, 20, 4, 12, 4, 8, 12, 12, 12, 20, 4, 12, 4, 8,
12, 12, 12, 20, 4, 12, 4, 8, 12, 12, 12, 20, 4, 12, 4, 8,
12, 12, 12, 20, 4, 12, 4, 16, 12, 12, 12, 20, 4, 12, 4, 16,
12, 12, 12, 20, 4, 12, 4, 4, 12, 12, 12, 20, 4, 12, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
16, 12, 16, 16, 4, 4, 4, 4, 16, 12, 16, 16, 4, 4, 4, 4,
16, 12, 16, 16, 4, 4, 4, 4, 16, 12, 16, 16, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
};
static const uint8_t amstrad_cycle_table_xy[256]=
{
4, 12, 8, 8, 4, 4, 8, 4, 4, 12, 8, 8, 4, 4, 8, 4,
12, 12, 8, 8, 4, 4, 8, 4, 12, 12, 8, 8, 4, 4, 8, 4,
8, 12, 20, 8, 4, 4, 8, 4, 8, 12, 20, 8, 4, 4, 8, 4,
8, 12, 16, 8, 20, 20, 20, 4, 8, 12, 16, 8, 4, 4, 8, 4,
4, 4, 4, 4, 4, 4, 16, 4, 4, 4, 4, 4, 4, 4, 16, 4,
4, 4, 4, 4, 4, 4, 16, 4, 4, 4, 4, 4, 4, 4, 16, 4,
4, 4, 4, 4, 4, 4, 16, 4, 4, 4, 4, 4, 4, 4, 16, 4,
16, 16, 16, 16, 16, 16, 4, 16, 4, 4, 4, 4, 4, 4, 16, 4,
4, 4, 4, 4, 4, 4, 16, 4, 4, 4, 4, 4, 4, 4, 16, 4,
4, 4, 4, 4, 4, 4, 16, 4, 4, 4, 4, 4, 4, 4, 16, 4,
4, 4, 4, 4, 4, 4, 16, 4, 4, 4, 4, 4, 4, 4, 16, 4,
4, 4, 4, 4, 4, 4, 16, 4, 4, 4, 4, 4, 4, 4, 16, 4,
8, 12, 12, 12, 12, 16, 8, 16, 8, 12, 12, 8, 12, 20, 8, 16,
8, 12, 12, 12, 12, 16, 8, 16, 8, 4, 12, 12, 12, 4, 8, 16,
8, 12, 12, 24, 12, 16, 8, 16, 8, 4, 12, 4, 12, 4, 8, 16,
8, 12, 12, 4, 12, 16, 8, 16, 8, 8, 12, 4, 12, 4, 8, 16
};
static const uint8_t amstrad_cycle_table_xycb[0x100] = {
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16
};
static const uint8_t amstrad_cycle_table_ex[256]=
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4, 8, 4, 4, 0, 0, 0, 0, 4, 8, 4, 4, 0, 0, 0, 0,
8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0,
8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0,
8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0,
8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0
};
#define NEXT_ROM_SLOT m_rom_count++; \
if(slot3 && m_rom_count == 3) m_rom_count++; \
if(slot7 && m_rom_count == 7) m_rom_count++;
@ -2935,6 +3036,26 @@ void amstrad_state::amstrad_common_init()
m_maincpu->set_input_line_vector(0, 0xff); // Z80
else
m_maincpu->set_input_line_vector(0, 0x00); // Z80
/* The opcode timing in the Amstrad is different to the opcode
timing in the core for the Z80 CPU.
The Amstrad hardware issues a HALT for each memory fetch.
This has the effect of stretching the timing for Z80 opcodes,
so that they are all multiple of 4 T states long. All opcode
timings are a multiple of 1us in length. */
/* Using the cool code Juergen has provided, I will override
the timing tables with the values for the amstrad */
m_maincpu->z80_set_cycle_tables(
(const uint8_t*)amstrad_cycle_table_op,
(const uint8_t*)amstrad_cycle_table_cb,
(const uint8_t*)amstrad_cycle_table_ed,
(const uint8_t*)amstrad_cycle_table_xy,
(const uint8_t*)amstrad_cycle_table_xycb,
(const uint8_t*)amstrad_cycle_table_ex);
/* Juergen is a cool dude! */
}
TIMER_CALLBACK_MEMBER(amstrad_state::cb_set_resolution)

View file

@ -314,10 +314,108 @@ void msx_state::machine_start()
m_port_c_old = 0xff;
}
// Update instruction timings to add 1 wait cycle for each M1 opcode fetch.
static const u8 cc_op[0x100] = {
4+1,10+1, 7+1, 6+1, 4+1, 4+1, 7+1, 4+1, 4+1,11+1, 7+1, 6+1, 4+1, 4+1, 7+1, 4+1,
8+1,10+1, 7+1, 6+1, 4+1, 4+1, 7+1, 4+1,12+1,11+1, 7+1, 6+1, 4+1, 4+1, 7+1, 4+1,
7+1,10+1,16+1, 6+1, 4+1, 4+1, 7+1, 4+1, 7+1,11+1,16+1, 6+1, 4+1, 4+1, 7+1, 4+1,
7+1,10+1,13+1, 6+1,11+1,11+1,10+1, 4+1, 7+1,11+1,13+1, 6+1, 4+1, 4+1, 7+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
7+1, 7+1, 7+1, 7+1, 7+1, 7+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
5+1,10+1,10+1,10+1,10+1,11+1, 7+1,11+1, 5+1,10+1,10+1, 4+1,10+1,17+1, 7+1,11+1,
5+1,10+1,10+1,11+1,10+1,11+1, 7+1,11+1, 5+1, 4+1,10+1,11+1,10+1, 4+1, 7+1,11+1,
5+1,10+1,10+1,19+1,10+1,11+1, 7+1,11+1, 5+1, 4+1,10+1, 4+1,10+1, 4+1, 7+1,11+1,
5+1,10+1,10+1, 4+1,10+1,11+1, 7+1,11+1, 5+1, 6+1,10+1, 4+1,10+1, 4+1, 7+1,11+1
};
static const u8 cc_cb[0x100] = {
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 8+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 8+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 8+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 8+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 8+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 8+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 8+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 8+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,11+1, 4+1
};
static const u8 cc_ed[0x100] = {
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,
8+1, 8+1,15+2,16+1, 4+1,14+2, 4+1, 5+1, 8+1, 8+1,15+2,16+1, 4+1,14+2, 4+1, 5+1,
8+1, 8+1,15+2,16+1, 4+1,14+2, 4+1, 5+1, 8+1, 8+1,15+2,16+1, 4+1,14+2, 4+1, 5+1,
8+1, 8+1,15+2,16+1, 4+1,14+2, 4+1,14+1, 8+1, 8+1,15+2,16+1, 4+1,14+2, 4+1,14+1,
8+1, 8+1,15+2,16+1, 4+1,14+2, 4+1, 4+1, 8+1, 8+1,15+2,16+1, 4+1,14+2, 4+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,
12+1,12+1,12+1,12+1, 4+1, 4+1, 4+1, 4+1,12+1,12+1,12+1,12+1, 4+1, 4+1, 4+1, 4+1,
12+1,12+1,12+1,12+1, 4+1, 4+1, 4+1, 4+1,12+1,12+1,12+1,12+1, 4+1, 4+1, 4+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1
};
static const u8 cc_xy[0x100] = {
4+1,10+1, 7+1, 6+1, 4+1, 4+1, 7+1, 4+1, 4+1,11+1, 7+1, 6+1, 4+1, 4+1, 7+1, 4+1,
8+1,10+1, 7+1, 6+1, 4+1, 4+1, 7+1, 4+1,12+1,11+1, 7+1, 6+1, 4+1, 4+1, 7+1, 4+1,
7+1,10+1,16+1, 6+1, 4+1, 4+1, 7+1, 4+1, 7+1,11+1,16+1, 6+1, 4+1, 4+1, 7+1, 4+1,
7+1,10+1,13+1, 6+1,19+1,19+1,15+1, 4+1, 7+1,11+1,13+1, 6+1, 4+1, 4+1, 7+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1,
15+1,15+1,15+1,15+1,15+1,15+1, 4+1,15+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1,
4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1,15+1, 4+1,
5+1,10+1,10+1,10+1,10+1,11+1, 7+1,11+1, 5+1,10+1,10+1, 7+1,10+1,17+1, 7+1,11+1,
5+1,10+1,10+1,11+1,10+1,11+1, 7+1,11+1, 5+1, 4+1,10+1,11+1,10+1, 4+1, 7+1,11+1,
5+1,10+1,10+1,19+1,10+1,11+1, 7+1,11+1, 5+1, 4+1,10+1, 4+1,10+1, 4+1, 7+1,11+1,
5+1,10+1,10+1, 4+1,10+1,11+1, 7+1,11+1, 5+1, 6+1,10+1, 4+1,10+1, 4+1, 7+1,11+1
};
/* extra cycles if jr/jp/call taken and 'interrupt latency' on rst 0-7 */
static const u8 cc_ex[0x100] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* DJNZ */
5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, /* JR NZ/JR Z */
5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, /* JR NC/JR C */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, /* LDIR/CPIR/INIR/OTIR LDDR/CPDR/INDR/OTDR */
6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2,
6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2,
6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2,
6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2+1
};
void msx_state::driver_start()
{
m_maincpu->set_input_line_vector(0, 0xff); // Z80
m_maincpu->z80_set_m1_cycles(5);
m_maincpu->z80_set_cycle_tables(cc_op, cc_cb, cc_ed, cc_xy, nullptr, cc_ex);
save_item(NAME(m_psg_b));
save_item(NAME(m_kanji_latch));