sinclair/sprinter.cpp: Improved interrupt timing and cleaned up code. (#11458)

This commit is contained in:
holub 2023-08-03 14:39:49 -04:00 committed by GitHub
parent 28a37a2aa0
commit 72c76f7606
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -74,28 +74,6 @@ TODO:
namespace {
#define X_SP 42_MHz_XTAL // TODO X1 after spectrumless
#define SPRINT_WIDTH 896
#define SPRINT_BORDER_RIGHT 48
#define SPRINT_SCREEN_XSIZE 640
#define SPRINT_BORDER_LEFT 48
#define SPRINT_XVIS (SPRINT_BORDER_RIGHT + SPRINT_SCREEN_XSIZE + SPRINT_BORDER_LEFT)
#define SPRINT_HEIGHT 320
#define SPRINT_BORDER_TOP 16
#define SPRINT_SCREEN_YSIZE 256
#define SPRINT_BORDER_BOTTOM 16
#define SPRINT_YVIS (SPRINT_BORDER_TOP + SPRINT_SCREEN_YSIZE + SPRINT_BORDER_BOTTOM)
#define ACC_ENA BIT(m_all_mode, 0)
#define CBL_MODE BIT(m_cbl_xx, 7)
#define CBL_STEREO BIT(m_cbl_xx, 6)
#define CBL_MODE16 BIT(m_cbl_xx, 5)
#define CBL_INT_ENA BIT(m_cbl_xx, 4)
#define RAM1 m_ram_pages[0xe9 - 0xc0]
#define RAM2 m_ram_pages[0xea - 0xc0]
class sprinter_state : public spectrum_128_state
{
public:
@ -157,11 +135,6 @@ protected:
required_device_array<isa8_device, 2> m_isa;
private:
static constexpr u16 BANK_RAM_MASK = 1 << 8;
static constexpr u16 BANK_FASTRAM_MASK = 1 << 9;
static constexpr u16 BANK_ISA_MASK = 1 << 10;
static constexpr u16 BANK_WRDISBL_MASK = 1 << 12;
enum accel_state : u8
{
OFF = 0, // ld b,b
@ -179,6 +152,34 @@ private:
MODE_NOP = 0xbe // cp (hl)
};
static constexpr XTAL X_SP = 42_MHz_XTAL; // TODO X1 after spectrumless
static constexpr u16 SPRINT_WIDTH = 896;
static constexpr u16 SPRINT_BORDER_RIGHT = 48;
static constexpr u16 SPRINT_SCREEN_XSIZE = 640;
static constexpr u16 SPRINT_BORDER_LEFT = 48;
static constexpr u16 SPRINT_XVIS = SPRINT_BORDER_RIGHT + SPRINT_SCREEN_XSIZE + SPRINT_BORDER_LEFT;
static constexpr u16 SPRINT_HEIGHT = 320;
static constexpr u16 SPRINT_BORDER_TOP = 16;
static constexpr u16 SPRINT_SCREEN_YSIZE = 256;
static constexpr u16 SPRINT_BORDER_BOTTOM = 16;
static constexpr u16 SPRINT_YVIS = SPRINT_BORDER_TOP + SPRINT_SCREEN_YSIZE + SPRINT_BORDER_BOTTOM;
static constexpr u16 BANK_RAM_MASK = 1 << 8;
static constexpr u16 BANK_FASTRAM_MASK = 1 << 9;
static constexpr u16 BANK_ISA_MASK = 1 << 10;
static constexpr u16 BANK_WRDISBL_MASK = 1 << 12;
bool acc_ena() const { return BIT(m_all_mode, 0); }
bool cbl_mode() const { return BIT(m_cbl_xx, 7); }
bool cbl_stereo() const { return BIT(m_cbl_xx, 6); }
bool cbl_mode16() const { return BIT(m_cbl_xx, 5); }
bool cbl_int_ena() const { return BIT(m_cbl_xx, 4); }
u8 ram1() const { return m_ram_pages[0xe9 - 0xc0]; }
u8 ram2() const { return m_ram_pages[0xea - 0xc0]; }
u8 dcp_r(offs_t offset);
void dcp_w(offs_t offset, u8 data);
@ -319,10 +320,10 @@ void sprinter_state::update_memory()
}
}
m_pages[1] = BANK_RAM_MASK | RAM1;
m_bank_ram[1]->set_entry(RAM1);
m_pages[2] = BANK_RAM_MASK | RAM2;
m_bank_ram[2]->set_entry(RAM2);
m_pages[1] = BANK_RAM_MASK | ram1();
m_bank_ram[1]->set_entry(ram1());
m_pages[2] = BANK_RAM_MASK | ram2();
m_bank_ram[2]->set_entry(ram2());
// 0xd0, 0xf0
m_pg3 = (BIT(~m_pn, 7) << 5) | 0x10 | (((BIT(m_sc, 4) && BIT(~m_cnf, 7)) || (BIT(m_cnf, 7) && BIT(m_pn, 6))) << 3) | (m_pn & 0x07);
@ -728,7 +729,7 @@ void sprinter_state::dcp_w(offs_t offset, u8 data)
break;
case 0x88:
if (CBL_MODE)
if (cbl_mode())
m_cbl_data[m_cbl_wa++] = data << 8;
else
{
@ -742,9 +743,9 @@ void sprinter_state::dcp_w(offs_t offset, u8 data)
m_cbl_xx = data;
m_cbl_cnt = 0;
m_cbl_wa = 0;
m_cbl_wae = CBL_MODE16;
m_cbl_wae = cbl_mode16();
const u8 divs[16] = {13, 9, 0, 0, 0, 0, 0, 0, 27, 19, 13, 9, 6, 4, 3, 1};
const attotime rate = (CBL_MODE && divs[m_cbl_xx & 15]) ? attotime::from_ticks(divs[m_cbl_xx & 15] + 1, X_SP / 192) : attotime::never;
const attotime rate = (cbl_mode() && divs[m_cbl_xx & 15]) ? attotime::from_ticks(divs[m_cbl_xx & 15] + 1, X_SP / 192) : attotime::never;
m_cbl_timer->adjust(rate, 0, rate);
break;
}
@ -1082,7 +1083,7 @@ void sprinter_state::ram_w(offs_t offset, u8 data)
}
else if ((m_acc_dir != OFF) && (page == 0xfd))
{
if (!CBL_MODE16)
if (!cbl_mode16())
m_cbl_data[m_cbl_wa++] = (data << 8);
else
{
@ -1150,15 +1151,22 @@ void sprinter_state::update_int(bool recalculate)
{
if (recalculate || m_ints.empty())
{
m_ints.clear();
for (auto a = 0; a <= 55; a++)
for (auto scr_b = 0; scr_b <= 39; scr_b++)
{
const u8* line1 = as_mode(a, 0);
for (auto b = 0; b <= 39; b++)
bool pre_int = false;
const u8 b = (scr_b + 40 - 2) % 40; // 2-top border
for (auto scr_a = 0; scr_a <= 55; scr_a++)
{
const u8 a = (scr_a + 56 - 6) % 56; // 3-left border, 3-teared blank?
const u8* line1 = as_mode(a, b);
if ((*line1 & 0xfd) == 0xfd)
m_ints.push_back({b * 8 + 23, a * 16 + 112});
line1 += 4;
pre_int = true;
else
{
if (pre_int)
m_ints.push_back({scr_b * 8 + 7, scr_a * 16}); // +7=bottom of the tile
pre_int = false;
}
}
}
}
@ -1178,7 +1186,7 @@ u8 sprinter_state::m1_r(offs_t offset)
u8 data = m_program.read_byte(offset);
m_z80_m1 = 0;
if (!machine().side_effects_disabled() && ACC_ENA)
if (!machine().side_effects_disabled() && acc_ena())
accel_control_r(data);
return data;
@ -1240,7 +1248,7 @@ void sprinter_state::init_taps()
{
if (!(m_pages[BIT(offset, 14, 2)] & (BANK_FASTRAM_MASK | BANK_ISA_MASK))) // ROM+RAM
do_cpu_wait();
if(!m_z80_m1 && ACC_ENA && (m_acc_dir != OFF))
if(!m_z80_m1 && acc_ena() && (m_acc_dir != OFF))
accel_r_tap(offset, data);
}
});
@ -1248,7 +1256,7 @@ void sprinter_state::init_taps()
{
if (!(m_pages[BIT(offset, 14, 2)] & 0xff00)) // ROM only, RAM(w) applies waits manually
do_cpu_wait();
if (!m_z80_m1 && ACC_ENA && (m_acc_dir != OFF))
if (!m_z80_m1 && acc_ena() && (m_acc_dir != OFF))
accel_w_tap(offset, data);
});
}
@ -1452,11 +1460,11 @@ u8 sprinter_state::kbd_fe_r(offs_t offset)
if (m_cassette->input() > 0.0038 )
data &= ~0x40;
if (CBL_MODE)
if (cbl_mode())
{
data &= ~0xa0;
data |= (m_screen->vpos() >= (SPRINT_BORDER_TOP + SPRINT_SCREEN_YSIZE)) << 5;
data |= (CBL_INT_ENA ? (m_cbl_cnt ^ m_cbl_wa) : m_cbl_cnt) & 0x80;
data |= (cbl_int_ena() ? (m_cbl_cnt ^ m_cbl_wa) : m_cbl_cnt) & 0x80;
}
return data;
@ -1487,7 +1495,7 @@ void sprinter_state::do_cpu_wait(bool is_io)
TIMER_CALLBACK_MEMBER(sprinter_state::irq_on)
{
m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE);
m_irq_off_timer->adjust(attotime::from_ticks(32, m_maincpu->unscaled_clock()));
m_irq_off_timer->adjust(attotime::from_ticks(26, m_maincpu->clock()));
update_int(false);
}
@ -1500,9 +1508,9 @@ TIMER_CALLBACK_MEMBER(sprinter_state::cbl_tick)
{
const u16 left = m_cbl_data[m_cbl_cnt++];
m_ldac->write(left);
m_rdac->write(CBL_STEREO ? m_cbl_data[m_cbl_cnt++] : left);
m_rdac->write(cbl_stereo() ? m_cbl_data[m_cbl_cnt++] : left);
if (CBL_INT_ENA && !(m_cbl_cnt & 0x7f))
if (cbl_int_ena() && !(m_cbl_cnt & 0x7f))
{
m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE);
m_irq_off_timer->adjust(attotime::never);
@ -1651,12 +1659,11 @@ INPUT_PORTS_START( sprinter )
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON6) PORT_NAME("Middle mouse button") PORT_CODE(MOUSECODE_BUTTON3)
PORT_START("NMI")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("NMI") PORT_CODE(KEYCODE_F11)
//PORT_START("NMI")
//PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("NMI") PORT_CODE(KEYCODE_F11)
PORT_START("TURBO")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Turbo") PORT_CODE(KEYCODE_F12) PORT_TOGGLE PORT_CHANGED_MEMBER(DEVICE_SELF, sprinter_state, turbo_changed, 0)
PORT_BIT(0xfe, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("TURBO") PORT_CODE(KEYCODE_F12) PORT_TOGGLE PORT_CHANGED_MEMBER(DEVICE_SELF, sprinter_state, turbo_changed, 0)
INPUT_PORTS_END
void sprinter_state::sprinter(machine_config &config)