* Spectrum graphics improvements (continuation of #9218). Routines have been cleaned and optimized based on the current state of graphics_device. All configurations are done in terms of T-States/pixels which will simplify adjustment to proper timings.
This commit is contained in:
parent
c783127ce8
commit
32ef8f7eed
@ -238,6 +238,10 @@ public:
|
|||||||
xtal.validate(std::string("Configuring screen ") + tag());
|
xtal.validate(std::string("Configuring screen ") + tag());
|
||||||
return set_raw(xtal.value(), htotal, hbend, hbstart, vtotal, vbend, vbstart);
|
return set_raw(xtal.value(), htotal, hbend, hbstart, vtotal, vbend, vbstart);
|
||||||
}
|
}
|
||||||
|
screen_device &set_raw(const XTAL &xtal, u16 htotal, u16 vtotal, rectangle visarea)
|
||||||
|
{
|
||||||
|
return set_raw(xtal, htotal, visarea.left(), visarea.right() + 1, vtotal, visarea.top(), visarea.bottom() + 1);
|
||||||
|
}
|
||||||
void set_refresh(attoseconds_t rate) { m_refresh = rate; }
|
void set_refresh(attoseconds_t rate) { m_refresh = rate; }
|
||||||
|
|
||||||
/// \brief Set refresh rate in Hertz
|
/// \brief Set refresh rate in Hertz
|
||||||
|
@ -578,7 +578,6 @@ void elwro800_state::elwro800(machine_config &config)
|
|||||||
screen.set_raw(14_MHz_XTAL / 2, 448, 0, SPEC_SCREEN_WIDTH, 312, 0, SPEC_SCREEN_HEIGHT);
|
screen.set_raw(14_MHz_XTAL / 2, 448, 0, SPEC_SCREEN_WIDTH, 312, 0, SPEC_SCREEN_HEIGHT);
|
||||||
// Sync and interrupt timings determined by 2716 EPROM
|
// Sync and interrupt timings determined by 2716 EPROM
|
||||||
screen.set_screen_update(FUNC(elwro800_state::screen_update_spectrum));
|
screen.set_screen_update(FUNC(elwro800_state::screen_update_spectrum));
|
||||||
screen.screen_vblank().set(FUNC(elwro800_state::screen_vblank_spectrum));
|
|
||||||
screen.set_palette("palette");
|
screen.set_palette("palette");
|
||||||
|
|
||||||
PALETTE(config, "palette", FUNC(elwro800_state::spectrum_palette), 16);
|
PALETTE(config, "palette", FUNC(elwro800_state::spectrum_palette), 16);
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#define PENTAGON_SCREEN rectangle{138, 393, 80, 271}
|
|
||||||
|
|
||||||
class pentagon_state : public spectrum_128_state
|
class pentagon_state : public spectrum_128_state
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -36,15 +34,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void machine_reset() override;
|
virtual void machine_reset() override;
|
||||||
virtual void video_start() override;
|
virtual void video_start() override;
|
||||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
|
||||||
{
|
|
||||||
TIMER_IRQ_ON,
|
|
||||||
TIMER_IRQ_OFF
|
|
||||||
};
|
|
||||||
|
|
||||||
void pentagon_port_7ffd_w(uint8_t data);
|
void pentagon_port_7ffd_w(uint8_t data);
|
||||||
void pentagon_scr_w(offs_t offset, uint8_t data);
|
void pentagon_scr_w(offs_t offset, uint8_t data);
|
||||||
void pentagon_scr2_w(offs_t offset, uint8_t data);
|
void pentagon_scr2_w(offs_t offset, uint8_t data);
|
||||||
@ -52,8 +43,6 @@ private:
|
|||||||
uint8_t beta_enable_r(offs_t offset);
|
uint8_t beta_enable_r(offs_t offset);
|
||||||
uint8_t beta_disable_r(offs_t offset);
|
uint8_t beta_disable_r(offs_t offset);
|
||||||
INTERRUPT_GEN_MEMBER(pentagon_interrupt);
|
INTERRUPT_GEN_MEMBER(pentagon_interrupt);
|
||||||
TIMER_CALLBACK_MEMBER(irq_on);
|
|
||||||
TIMER_CALLBACK_MEMBER(irq_off);
|
|
||||||
void pentagon_io(address_map &map);
|
void pentagon_io(address_map &map);
|
||||||
void pentagon_mem(address_map &map);
|
void pentagon_mem(address_map &map);
|
||||||
void pentagon_switch(address_map &map);
|
void pentagon_switch(address_map &map);
|
||||||
@ -67,30 +56,19 @@ private:
|
|||||||
address_space *m_program;
|
address_space *m_program;
|
||||||
uint8_t *m_p_ram;
|
uint8_t *m_p_ram;
|
||||||
void pentagon_update_memory();
|
void pentagon_update_memory();
|
||||||
|
rectangle get_screen_area() override;
|
||||||
// Redefined here as POC of improved screen porocessing. Intended to update original implementation.
|
|
||||||
void to_display(unsigned int &x, unsigned int &y);
|
|
||||||
void spectrum_UpdateScreenBitmap(bool eof = false) override;
|
|
||||||
// Following 2 are obsolete
|
|
||||||
u32 screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) override;
|
|
||||||
void spectrum_UpdateBorderBitmap() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void pentagon_state::pentagon_update_memory()
|
void pentagon_state::pentagon_update_memory()
|
||||||
{
|
{
|
||||||
uint8_t *messram = m_ram->pointer();
|
uint8_t *messram = m_ram->pointer();
|
||||||
|
|
||||||
m_screen_location = messram + ((m_port_7ffd_data & 8) ? (7<<14) : (5<<14));
|
m_screen_location = messram + ((m_port_7ffd_data & 8) ? (7<<14) : (5<<14));
|
||||||
|
|
||||||
if (strcmp(machine().system().name, "pent1024") != 0)
|
if (strcmp(machine().system().name, "pent1024") != 0)
|
||||||
{
|
|
||||||
m_bank4->set_base(messram + ((m_port_7ffd_data & 0x07) * 0x4000));
|
m_bank4->set_base(messram + ((m_port_7ffd_data & 0x07) * 0x4000));
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
// currently 512Kb ram expansion supported
|
// currently 512Kb ram expansion supported
|
||||||
m_bank4->set_base(messram + (((m_port_7ffd_data & 0x07) | ((m_port_7ffd_data & 0xc0) >> 3)) * 0x4000));
|
m_bank4->set_base(messram + (((m_port_7ffd_data & 0x07) | ((m_port_7ffd_data & 0xc0) >> 3)) * 0x4000));
|
||||||
}
|
|
||||||
|
|
||||||
if (m_beta->started() && m_beta->is_active() && !( m_port_7ffd_data & 0x10 ) )
|
if (m_beta->started() && m_beta->is_active() && !( m_port_7ffd_data & 0x10 ) )
|
||||||
{
|
{
|
||||||
@ -115,7 +93,7 @@ void pentagon_state::pentagon_port_7ffd_w(uint8_t data)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if ((m_port_7ffd_data ^ data) & 0x08)
|
if ((m_port_7ffd_data ^ data) & 0x08)
|
||||||
spectrum_UpdateScreenBitmap();
|
m_screen->update_now();
|
||||||
|
|
||||||
/* store new state */
|
/* store new state */
|
||||||
m_port_7ffd_data = data;
|
m_port_7ffd_data = data;
|
||||||
@ -126,121 +104,27 @@ void pentagon_state::pentagon_port_7ffd_w(uint8_t data)
|
|||||||
|
|
||||||
void pentagon_state::pentagon_scr_w(offs_t offset, uint8_t data)
|
void pentagon_state::pentagon_scr_w(offs_t offset, uint8_t data)
|
||||||
{
|
{
|
||||||
spectrum_UpdateScreenBitmap();
|
m_screen->update_now();
|
||||||
|
|
||||||
*((uint8_t*)m_bank2->base() + offset) = data;
|
*((uint8_t*)m_bank2->base() + offset) = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pentagon_state::pentagon_scr2_w(offs_t offset, uint8_t data)
|
void pentagon_state::pentagon_scr2_w(offs_t offset, uint8_t data)
|
||||||
{
|
{
|
||||||
if ((m_port_7ffd_data & 0x0f) == 0x0f || (m_port_7ffd_data & 0x0f) == 5)
|
if ((m_port_7ffd_data & 0x0f) == 0x0f || (m_port_7ffd_data & 0x0f) == 5)
|
||||||
spectrum_UpdateScreenBitmap();
|
m_screen->update_now();
|
||||||
|
|
||||||
*((uint8_t*)m_bank4->base() + offset) = data;
|
*((uint8_t*)m_bank4->base() + offset) = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This one not needed as we draw directly at screen's bitmap.
|
rectangle pentagon_state::get_screen_area()
|
||||||
u32 pentagon_state::screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
|
||||||
{
|
{
|
||||||
return 0;
|
//TODO Possible because of incorrect z80 we have to adjust x+1 to make AccrossTheEdge look nicer
|
||||||
}
|
return rectangle{137, 137 + 255, 80, 80 + 191};
|
||||||
|
|
||||||
void pentagon_state::to_display(unsigned int &x, unsigned int &y)
|
|
||||||
{
|
|
||||||
rectangle va = m_screen->visible_area();
|
|
||||||
if(y < va.top() || y > va.bottom()) {
|
|
||||||
x = va.left();
|
|
||||||
y = va.top();
|
|
||||||
} else if(x < va.left()) {
|
|
||||||
x = va.left();
|
|
||||||
} else if(x > va.right()) {
|
|
||||||
x = va.left();
|
|
||||||
y++;
|
|
||||||
to_display(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void pentagon_state::spectrum_UpdateScreenBitmap(bool eof)
|
|
||||||
{
|
|
||||||
unsigned int to_x = m_screen->hpos();
|
|
||||||
unsigned int to_y = m_screen->vpos();
|
|
||||||
to_display(to_x, to_y);
|
|
||||||
|
|
||||||
if ((m_previous_screen_x == to_x) && (m_previous_screen_y == to_y) && !eof)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bitmap_ind16 *bm = &m_screen->curbitmap().as_ind16();
|
|
||||||
if (bm->valid())
|
|
||||||
{
|
|
||||||
u16 border_color = get_border_color();
|
|
||||||
do
|
|
||||||
{
|
|
||||||
u16 x = m_previous_screen_x - PENTAGON_SCREEN.left();
|
|
||||||
u16 y = m_previous_screen_y - PENTAGON_SCREEN.top();
|
|
||||||
|
|
||||||
if(PENTAGON_SCREEN.contains(m_previous_screen_x, m_previous_screen_y))
|
|
||||||
{
|
|
||||||
// this can/must be optimised
|
|
||||||
if ((x & 7) == 0)
|
|
||||||
{
|
|
||||||
u16 *pix = &bm->pix(m_previous_screen_y, m_previous_screen_x);
|
|
||||||
u8 attr = *(m_screen_location + ((y & 0xF8) << 2) + (x >> 3) + 0x1800);
|
|
||||||
u8 scr = *(m_screen_location + ((y & 7) << 8) + ((y & 0x38) << 2) + ((y & 0xC0) << 5) + (x >> 3));
|
|
||||||
u16 ink = (attr & 0x07) + ((attr >> 3) & 0x08);
|
|
||||||
u16 pap = (attr >> 3) & 0x0f;
|
|
||||||
|
|
||||||
if (m_flash_invert && (attr & 0x80))
|
|
||||||
scr = ~scr;
|
|
||||||
|
|
||||||
for (uint8_t b = 0x80; b != 0; b >>= 1)
|
|
||||||
*pix++ = (scr & b) ? ink : pap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bm->pix(m_previous_screen_y, m_previous_screen_x) = border_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
to_display(++m_previous_screen_x, m_previous_screen_y);
|
|
||||||
} while (!((m_previous_screen_x == to_x) && (m_previous_screen_y == to_y)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Any calls must be replaced with spectrum_UpdateScreenBitmap()
|
|
||||||
void pentagon_state::spectrum_UpdateBorderBitmap()
|
|
||||||
{
|
|
||||||
spectrum_UpdateScreenBitmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pentagon_state::device_timer(emu_timer &timer, device_timer_id id, int param)
|
|
||||||
{
|
|
||||||
switch (id)
|
|
||||||
{
|
|
||||||
case TIMER_IRQ_ON:
|
|
||||||
irq_on(param);
|
|
||||||
break;
|
|
||||||
case TIMER_IRQ_OFF:
|
|
||||||
irq_off(param);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw emu_fatalerror("Unknown id in pentagon_state::device_timer");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TIMER_CALLBACK_MEMBER(pentagon_state::irq_on)
|
|
||||||
{
|
|
||||||
m_maincpu->set_input_line(0, HOLD_LINE);
|
|
||||||
timer_set(attotime::from_ticks(32, XTAL(14'000'000) / 4), TIMER_IRQ_OFF, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
TIMER_CALLBACK_MEMBER(pentagon_state::irq_off)
|
|
||||||
{
|
|
||||||
m_maincpu->set_input_line(0, CLEAR_LINE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERRUPT_GEN_MEMBER(pentagon_state::pentagon_interrupt)
|
INTERRUPT_GEN_MEMBER(pentagon_state::pentagon_interrupt)
|
||||||
{
|
{
|
||||||
timer_set(attotime::zero, TIMER_IRQ_ON, 0);
|
timer_set(m_screen->time_until_pos(0) - m_maincpu->clocks_to_attotime(1), TIMER_IRQ_ON, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t pentagon_state::beta_neutral_r(offs_t offset)
|
uint8_t pentagon_state::beta_neutral_r(offs_t offset)
|
||||||
@ -335,46 +219,35 @@ void pentagon_state::machine_reset()
|
|||||||
void pentagon_state::video_start()
|
void pentagon_state::video_start()
|
||||||
{
|
{
|
||||||
m_frame_invert_count = 16;
|
m_frame_invert_count = 16;
|
||||||
m_frame_number = 0;
|
|
||||||
m_flash_invert = 0;
|
|
||||||
|
|
||||||
m_previous_border_x = m_previous_border_y = 0;
|
|
||||||
m_previous_screen_x = m_previous_screen_y = 0;
|
|
||||||
|
|
||||||
m_screen_location = m_ram->pointer() + (5 << 14);
|
m_screen_location = m_ram->pointer() + (5 << 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* F4 Character Displayer */
|
|
||||||
static const gfx_layout spectrum_charlayout =
|
static const gfx_layout spectrum_charlayout =
|
||||||
{
|
{
|
||||||
8, 8, /* 8 x 8 characters */
|
8, 8, /* 8 x 8 characters */
|
||||||
96, /* 96 characters */
|
96, /* 96 characters */
|
||||||
1, /* 1 bits per pixel */
|
1, /* 1 bits per pixel */
|
||||||
{ 0 }, /* no bitplanes */
|
{ 0 }, /* no bitplanes */
|
||||||
/* x offsets */
|
{STEP8(0, 1)}, /* x offsets */
|
||||||
{ 0, 1, 2, 3, 4, 5, 6, 7 },
|
{STEP8(0, 8)}, /* y offsets */
|
||||||
/* y offsets */
|
|
||||||
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
|
|
||||||
8*8 /* every char takes 8 bytes */
|
8*8 /* every char takes 8 bytes */
|
||||||
};
|
};
|
||||||
|
|
||||||
static GFXDECODE_START( gfx_pentagon )
|
static GFXDECODE_START( gfx_pentagon )
|
||||||
GFXDECODE_ENTRY( "maincpu", 0x17d00, spectrum_charlayout, 0, 8 )
|
GFXDECODE_ENTRY( "maincpu", 0x17d00, spectrum_charlayout, 7, 8 )
|
||||||
GFXDECODE_END
|
GFXDECODE_END
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void pentagon_state::pentagon(machine_config &config)
|
void pentagon_state::pentagon(machine_config &config)
|
||||||
{
|
{
|
||||||
spectrum_128(config);
|
spectrum_128(config);
|
||||||
m_maincpu->set_clock(XTAL(14'000'000) / 4);
|
m_maincpu->set_clock(14_MHz_XTAL / 4);
|
||||||
m_maincpu->set_addrmap(AS_PROGRAM, &pentagon_state::pentagon_mem);
|
m_maincpu->set_addrmap(AS_PROGRAM, &pentagon_state::pentagon_mem);
|
||||||
m_maincpu->set_addrmap(AS_IO, &pentagon_state::pentagon_io);
|
m_maincpu->set_addrmap(AS_IO, &pentagon_state::pentagon_io);
|
||||||
m_maincpu->set_addrmap(AS_OPCODES, &pentagon_state::pentagon_switch);
|
m_maincpu->set_addrmap(AS_OPCODES, &pentagon_state::pentagon_switch);
|
||||||
m_maincpu->set_vblank_int("screen", FUNC(pentagon_state::pentagon_interrupt));
|
m_maincpu->set_vblank_int("screen", FUNC(pentagon_state::pentagon_interrupt));
|
||||||
|
|
||||||
//m_screen->set_raw(XTAL(14'000'000) / 2, 448, 0, 352, 320, 0, 304);
|
m_screen->set_raw(14_MHz_XTAL / 2, 448, 320, {get_screen_area().left() - 48, get_screen_area().right() + 48, get_screen_area().top() - 48, get_screen_area().bottom() + 48});
|
||||||
m_screen->set_raw(XTAL(14'000'000) / 2, 448, PENTAGON_SCREEN.left() - 48, PENTAGON_SCREEN.right() + 49, 320, PENTAGON_SCREEN.top() - 48, PENTAGON_SCREEN.bottom() + 49);
|
|
||||||
|
|
||||||
BETA_DISK(config, m_beta, 0);
|
BETA_DISK(config, m_beta, 0);
|
||||||
subdevice<gfxdecode_device>("gfxdecode")->set_info(gfx_pentagon);
|
subdevice<gfxdecode_device>("gfxdecode")->set_info(gfx_pentagon);
|
||||||
@ -382,7 +255,7 @@ void pentagon_state::pentagon(machine_config &config)
|
|||||||
SPEAKER(config, "lspeaker").front_left();
|
SPEAKER(config, "lspeaker").front_left();
|
||||||
SPEAKER(config, "rspeaker").front_right();
|
SPEAKER(config, "rspeaker").front_right();
|
||||||
|
|
||||||
ay8912_device &ay8912(AY8912(config.replace(), "ay8912", XTAL(14'000'000)/8));
|
ay8912_device &ay8912(AY8912(config.replace(), "ay8912", 14_MHz_XTAL / 8));
|
||||||
ay8912.add_route(0, "lspeaker", 0.50);
|
ay8912.add_route(0, "lspeaker", 0.50);
|
||||||
ay8912.add_route(1, "lspeaker", 0.25);
|
ay8912.add_route(1, "lspeaker", 0.25);
|
||||||
ay8912.add_route(1, "rspeaker", 0.25);
|
ay8912.add_route(1, "rspeaker", 0.25);
|
||||||
@ -479,5 +352,5 @@ ROM_END
|
|||||||
|
|
||||||
|
|
||||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||||
COMP( 1991, pentagon, spec128, 0, pentagon, spec_plus, pentagon_state, empty_init, "<unknown>", "Pentagon 128K", 0 )
|
COMP( 1991, pentagon, spec128, 0, pentagon, spec_plus, pentagon_state, empty_init, "Vladimir Drozdov", "Pentagon 128K", 0 )
|
||||||
COMP( 2005, pent1024, spec128, 0, pent1024, spec_plus, pentagon_state, empty_init, "<unknown>", "Pentagon 1024SL", 0 )
|
COMP( 2005, pent1024, spec128, 0, pent1024, spec_plus, pentagon_state, empty_init, "Alex Zhabin", "Pentagon 1024SL", 0 )
|
||||||
|
@ -213,7 +213,7 @@ void spectrum_128_state::spectrum_128_port_7ffd_w(offs_t offset, uint8_t data)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if ((m_port_7ffd_data ^ data) & 0x08)
|
if ((m_port_7ffd_data ^ data) & 0x08)
|
||||||
spectrum_UpdateScreenBitmap();
|
m_screen->update_now();
|
||||||
|
|
||||||
/* store new state */
|
/* store new state */
|
||||||
m_port_7ffd_data = data;
|
m_port_7ffd_data = data;
|
||||||
@ -248,19 +248,6 @@ uint8_t spectrum_128_state::spectrum_port_r(offs_t offset)
|
|||||||
return floating_bus_r();
|
return floating_bus_r();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t spectrum_128_state::floating_bus_r()
|
|
||||||
{
|
|
||||||
// very basic "floating bus" implementation, see notes in spectrum.cpp
|
|
||||||
uint8_t data = 0xff;
|
|
||||||
int hpos = m_screen->hpos();
|
|
||||||
int vpos = m_screen->vpos();
|
|
||||||
|
|
||||||
if ((hpos >= 48 && hpos < 304) && (vpos >= 48 && vpos < 240))
|
|
||||||
data = m_screen_location[0x1800 + (((vpos-48)/8)*32) + ((hpos-48)/8)];
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spectrum_128_state::spectrum_128_io(address_map &map)
|
void spectrum_128_state::spectrum_128_io(address_map &map)
|
||||||
{
|
{
|
||||||
map(0x0000, 0x0000).select(0xfffe).rw(FUNC(spectrum_128_state::spectrum_ula_r), FUNC(spectrum_128_state::spectrum_ula_w));
|
map(0x0000, 0x0000).select(0xfffe).rw(FUNC(spectrum_128_state::spectrum_ula_r), FUNC(spectrum_128_state::spectrum_ula_w));
|
||||||
@ -304,30 +291,31 @@ void spectrum_128_state::machine_reset()
|
|||||||
spectrum_128_update_memory();
|
spectrum_128_update_memory();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* F4 Character Displayer */
|
|
||||||
static const gfx_layout spectrum_charlayout =
|
static const gfx_layout spectrum_charlayout =
|
||||||
{
|
{
|
||||||
8, 8, /* 8 x 8 characters */
|
8, 8, /* 8 x 8 characters */
|
||||||
96, /* 96 characters */
|
96, /* 96 characters */
|
||||||
1, /* 1 bits per pixel */
|
1, /* 1 bits per pixel */
|
||||||
{ 0 }, /* no bitplanes */
|
{ 0 }, /* no bitplanes */
|
||||||
/* x offsets */
|
{STEP8(0, 1)}, /* x offsets */
|
||||||
{ 0, 1, 2, 3, 4, 5, 6, 7 },
|
{STEP8(0, 8)}, /* y offsets */
|
||||||
/* y offsets */
|
|
||||||
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
|
|
||||||
8*8 /* every char takes 8 bytes */
|
8*8 /* every char takes 8 bytes */
|
||||||
};
|
};
|
||||||
|
|
||||||
static GFXDECODE_START( spec128 )
|
static GFXDECODE_START( spec128 )
|
||||||
GFXDECODE_ENTRY( "maincpu", 0x17d00, spectrum_charlayout, 0, 8 )
|
GFXDECODE_ENTRY( "maincpu", 0x17d00, spectrum_charlayout, 7, 8 )
|
||||||
GFXDECODE_END
|
GFXDECODE_END
|
||||||
|
|
||||||
|
rectangle spectrum_128_state::get_screen_area()
|
||||||
|
{
|
||||||
|
return rectangle{48, 48 + 255, 63, 63 + 191};
|
||||||
|
}
|
||||||
|
|
||||||
void spectrum_128_state::spectrum_128(machine_config &config)
|
void spectrum_128_state::spectrum_128(machine_config &config)
|
||||||
{
|
{
|
||||||
spectrum(config);
|
spectrum(config);
|
||||||
|
|
||||||
Z80(config.replace(), m_maincpu, X1_128_SINCLAIR / 5);
|
Z80(config.replace(), m_maincpu, X1_128_SINCLAIR / 10);
|
||||||
m_maincpu->set_addrmap(AS_PROGRAM, &spectrum_128_state::spectrum_128_mem);
|
m_maincpu->set_addrmap(AS_PROGRAM, &spectrum_128_state::spectrum_128_mem);
|
||||||
m_maincpu->set_addrmap(AS_IO, &spectrum_128_state::spectrum_128_io);
|
m_maincpu->set_addrmap(AS_IO, &spectrum_128_state::spectrum_128_io);
|
||||||
m_maincpu->set_addrmap(AS_OPCODES, &spectrum_128_state::spectrum_128_fetch);
|
m_maincpu->set_addrmap(AS_OPCODES, &spectrum_128_state::spectrum_128_fetch);
|
||||||
@ -335,12 +323,12 @@ void spectrum_128_state::spectrum_128(machine_config &config)
|
|||||||
config.set_maximum_quantum(attotime::from_hz(60));
|
config.set_maximum_quantum(attotime::from_hz(60));
|
||||||
|
|
||||||
/* video hardware */
|
/* video hardware */
|
||||||
m_screen->set_raw(X1_128_SINCLAIR / 2.5, 456, 0, 352, 311, 0, 296);
|
m_screen->set_raw(X1_128_SINCLAIR / 5, 456, 311, {get_screen_area().left() - 48, get_screen_area().right() + 48, get_screen_area().top() - 48, get_screen_area().bottom() + 48});
|
||||||
|
|
||||||
subdevice<gfxdecode_device>("gfxdecode")->set_info(spec128);
|
subdevice<gfxdecode_device>("gfxdecode")->set_info(spec128);
|
||||||
|
|
||||||
/* sound hardware */
|
/* sound hardware */
|
||||||
AY8912(config, "ay8912", X1_128_SINCLAIR / 10).add_route(ALL_OUTPUTS, "mono", 0.25);
|
AY8912(config, "ay8912", X1_128_SINCLAIR / 20).add_route(ALL_OUTPUTS, "mono", 0.25);
|
||||||
|
|
||||||
/* expansion port */
|
/* expansion port */
|
||||||
SPECTRUM_EXPANSION_SLOT(config.replace(), m_exp, spec128_expansion_devices, nullptr);
|
SPECTRUM_EXPANSION_SLOT(config.replace(), m_exp, spec128_expansion_devices, nullptr);
|
||||||
@ -353,15 +341,12 @@ void spectrum_128_state::spectrum_128(machine_config &config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
|
||||||
Game driver(s)
|
Game driver(s)
|
||||||
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
ROM_START(spec128)
|
ROM_START(spec128)
|
||||||
ROM_REGION(0x18000,"maincpu",0)
|
ROM_REGION(0x18000,"maincpu",0)
|
||||||
ROM_SYSTEM_BIOS( 0, "en", "English" )
|
ROM_SYSTEM_BIOS( 0, "en", "English" )
|
||||||
|
@ -339,30 +339,21 @@ uint8_t spectrum_state::spectrum_rom_r(offs_t offset)
|
|||||||
bit 3: MIC/Tape Output
|
bit 3: MIC/Tape Output
|
||||||
bit 2-0: border colour
|
bit 2-0: border colour
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void spectrum_state::spectrum_ula_w(offs_t offset, uint8_t data)
|
void spectrum_state::spectrum_ula_w(offs_t offset, uint8_t data)
|
||||||
{
|
{
|
||||||
unsigned char Changed;
|
unsigned char Changed = m_port_fe_data^data;
|
||||||
|
|
||||||
Changed = m_port_fe_data^data;
|
|
||||||
|
|
||||||
/* border colour changed? */
|
/* border colour changed? */
|
||||||
if ((Changed & 0x07)!=0)
|
if ((Changed & 0x07)!=0)
|
||||||
{
|
m_screen->update_now();
|
||||||
spectrum_UpdateBorderBitmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((Changed & (1<<4))!=0)
|
if ((Changed & (1<<4))!=0)
|
||||||
{
|
|
||||||
/* DAC output state */
|
/* DAC output state */
|
||||||
m_speaker->level_w(BIT(data, 4));
|
m_speaker->level_w(BIT(data, 4));
|
||||||
}
|
|
||||||
|
|
||||||
if ((Changed & (1<<3))!=0)
|
if ((Changed & (1<<3))!=0)
|
||||||
{
|
|
||||||
/* write cassette data */
|
/* write cassette data */
|
||||||
m_cassette->output((data & (1<<3)) ? -1.0 : +1.0);
|
m_cassette->output((data & (1<<3)) ? -1.0 : +1.0);
|
||||||
}
|
|
||||||
|
|
||||||
// Some exp devices use ula port unused bits 5-7:
|
// Some exp devices use ula port unused bits 5-7:
|
||||||
// Beta v2/3/plus use bit 7, Beta clones use bits 6 and 7
|
// Beta v2/3/plus use bit 7, Beta clones use bits 6 and 7
|
||||||
@ -508,8 +499,9 @@ uint8_t spectrum_state::floating_bus_r()
|
|||||||
// peek into attribute ram when beam is in display area
|
// peek into attribute ram when beam is in display area
|
||||||
// ula always returns ff when in border area (or h/vblank)
|
// ula always returns ff when in border area (or h/vblank)
|
||||||
|
|
||||||
if ((hpos >= 48 && hpos < 304) && (vpos >= 48 && vpos < 240))
|
rectangle screen = get_screen_area();
|
||||||
data = m_video_ram[0x1800 + (((vpos-48)/8)*32) + ((hpos-48)/8)];
|
if (screen.contains(hpos, vpos))
|
||||||
|
data = m_screen_location[0x1800 + (((vpos - screen.top()) / 8) * 32) + ((hpos - screen.left()) / 8)];
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -713,12 +705,17 @@ INPUT_PORTS_START( spec_plus )
|
|||||||
INPUT_PORTS_END
|
INPUT_PORTS_END
|
||||||
|
|
||||||
/* Machine initialization */
|
/* Machine initialization */
|
||||||
|
|
||||||
void spectrum_state::init_spectrum()
|
void spectrum_state::init_spectrum()
|
||||||
{
|
{
|
||||||
m_specmem->space(AS_PROGRAM).install_ram(0x5b00, m_ram->size() + 0x3fff, m_ram->pointer() + 0x1b00);
|
m_specmem->space(AS_PROGRAM).install_ram(0x5b00, m_ram->size() + 0x3fff, m_ram->pointer() + 0x1b00);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void spectrum_state::machine_start()
|
||||||
|
{
|
||||||
|
save_item(NAME(m_port_fe_data));
|
||||||
|
//TODO more
|
||||||
|
}
|
||||||
|
|
||||||
void spectrum_state::machine_reset()
|
void spectrum_state::machine_reset()
|
||||||
{
|
{
|
||||||
m_port_7ffd_data = -1;
|
m_port_7ffd_data = -1;
|
||||||
@ -732,28 +729,35 @@ static const gfx_layout spectrum_charlayout =
|
|||||||
96, /* 96 characters */
|
96, /* 96 characters */
|
||||||
1, /* 1 bits per pixel */
|
1, /* 1 bits per pixel */
|
||||||
{ 0 }, /* no bitplanes */
|
{ 0 }, /* no bitplanes */
|
||||||
/* x offsets */
|
{STEP8(0, 1)}, /* x offsets */
|
||||||
{ 0, 1, 2, 3, 4, 5, 6, 7 },
|
{STEP8(0, 8)}, /* y offsets */
|
||||||
/* y offsets */
|
|
||||||
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
|
|
||||||
8*8 /* every char takes 8 bytes */
|
8*8 /* every char takes 8 bytes */
|
||||||
};
|
};
|
||||||
|
|
||||||
static GFXDECODE_START( gfx_spectrum )
|
static GFXDECODE_START( gfx_spectrum )
|
||||||
GFXDECODE_ENTRY( "maincpu", 0x3d00, spectrum_charlayout, 0, 8 )
|
GFXDECODE_ENTRY( "maincpu", 0x3d00, spectrum_charlayout, 7, 8 )
|
||||||
GFXDECODE_END
|
GFXDECODE_END
|
||||||
|
|
||||||
void spectrum_state::device_timer(emu_timer &timer, device_timer_id id, int param)
|
void spectrum_state::device_timer(emu_timer &timer, device_timer_id id, int param)
|
||||||
{
|
{
|
||||||
switch (id)
|
switch (id)
|
||||||
{
|
{
|
||||||
|
case TIMER_IRQ_ON:
|
||||||
|
m_maincpu->set_input_line(0, HOLD_LINE);
|
||||||
|
timer_set(m_maincpu->clocks_to_attotime(32), TIMER_IRQ_OFF, 0);
|
||||||
|
break;
|
||||||
case TIMER_IRQ_OFF:
|
case TIMER_IRQ_OFF:
|
||||||
m_maincpu->set_input_line(0, CLEAR_LINE);
|
m_maincpu->set_input_line(0, CLEAR_LINE);
|
||||||
break;
|
break;
|
||||||
case TIMER_SCANLINE:
|
case TIMER_SCANLINE:
|
||||||
m_scanline_timer->adjust(m_maincpu->cycles_to_attotime(m_CyclesPerLine));
|
{
|
||||||
spectrum_UpdateScreenBitmap();
|
auto vpos_next = m_screen->vpos() + 1;
|
||||||
|
if(vpos_next <= get_screen_area().bottom()) {
|
||||||
|
m_scanline_timer->adjust(m_screen->time_until_pos(vpos_next), get_screen_area().left());
|
||||||
|
m_screen->update_now();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw emu_fatalerror("Unknown id in spectrum_state::device_timer");
|
throw emu_fatalerror("Unknown id in spectrum_state::device_timer");
|
||||||
}
|
}
|
||||||
@ -761,8 +765,14 @@ void spectrum_state::device_timer(emu_timer &timer, device_timer_id id, int para
|
|||||||
|
|
||||||
INTERRUPT_GEN_MEMBER(spectrum_state::spec_interrupt)
|
INTERRUPT_GEN_MEMBER(spectrum_state::spec_interrupt)
|
||||||
{
|
{
|
||||||
m_maincpu->set_input_line(0, ASSERT_LINE);
|
timer_set(m_screen->time_until_pos(0), TIMER_IRQ_ON, 0);
|
||||||
m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32));
|
|
||||||
|
/* Default implementation performs screen updates per scanline. Some other
|
||||||
|
clones e.g. pentagon do updates based on video_ram access, border updates,
|
||||||
|
and full frame refresh (for attributes flashing). Such clones may define own
|
||||||
|
*_interrupt config. */
|
||||||
|
if (m_scanline_timer != nullptr)
|
||||||
|
m_scanline_timer->adjust(m_screen->time_until_pos(get_screen_area().top() + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void spectrum_state::spectrum_common(machine_config &config)
|
void spectrum_state::spectrum_common(machine_config &config)
|
||||||
@ -784,9 +794,9 @@ void spectrum_state::spectrum_common(machine_config &config)
|
|||||||
|
|
||||||
/* video hardware */
|
/* video hardware */
|
||||||
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
|
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
|
||||||
m_screen->set_raw(X1 / 2, 448, 0, 352, 312, 0, 296);
|
|
||||||
|
m_screen->set_raw(X1 / 2, 448, 312, {get_screen_area().left() - 48, get_screen_area().right() + 48, get_screen_area().top() - 48, get_screen_area().bottom() + 48});
|
||||||
m_screen->set_screen_update(FUNC(spectrum_state::screen_update_spectrum));
|
m_screen->set_screen_update(FUNC(spectrum_state::screen_update_spectrum));
|
||||||
m_screen->screen_vblank().set(FUNC(spectrum_state::screen_vblank_spectrum));
|
|
||||||
m_screen->set_palette("palette");
|
m_screen->set_palette("palette");
|
||||||
|
|
||||||
PALETTE(config, "palette", FUNC(spectrum_state::spectrum_palette), 16);
|
PALETTE(config, "palette", FUNC(spectrum_state::spectrum_palette), 16);
|
||||||
@ -1151,7 +1161,7 @@ COMP( 1993, didakm93, spectrum, 0, spectrum_clone, spec_plus, spectrum_stat
|
|||||||
COMP( 1988, mistrum, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "Amaterske RADIO", "Mistrum", 0 ) // keyboard could be spectrum in some models (since it was a build-yourself design)
|
COMP( 1988, mistrum, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "Amaterske RADIO", "Mistrum", 0 ) // keyboard could be spectrum in some models (since it was a build-yourself design)
|
||||||
COMP( 198?, bk08, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "Orel", "BK-08", 0 )
|
COMP( 198?, bk08, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "Orel", "BK-08", 0 )
|
||||||
COMP( 1990, blitzs, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "<unknown>", "Blic", 0 ) // no keyboard images found
|
COMP( 1990, blitzs, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "<unknown>", "Blic", 0 ) // no keyboard images found
|
||||||
COMP( 1990, byte, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "<unknown>", "Byte", 0 ) // no keyboard images found
|
COMP( 1990, byte, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "BEMZ", "PEVM Byte", 0 ) // no keyboard images found
|
||||||
COMP( 199?, orizon, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "<unknown>", "Orizon-Micro", 0 ) // no keyboard images found
|
COMP( 199?, orizon, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "<unknown>", "Orizon-Micro", 0 ) // no keyboard images found
|
||||||
COMP( 1993, quorum48, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "<unknown>", "Kvorum 48K", MACHINE_NOT_WORKING )
|
COMP( 1993, quorum48, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "<unknown>", "Kvorum 48K", MACHINE_NOT_WORKING )
|
||||||
COMP( 1993, magic6, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "<unknown>", "Magic 6", MACHINE_NOT_WORKING ) // keyboard should be spectrum, but image was not clear
|
COMP( 1993, magic6, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "<unknown>", "Magic 6", MACHINE_NOT_WORKING ) // keyboard should be spectrum, but image was not clear
|
||||||
|
@ -165,23 +165,23 @@ http://www.z88forever.org.uk/zxplus3e/
|
|||||||
/* TS2048 specific functions */
|
/* TS2048 specific functions */
|
||||||
|
|
||||||
|
|
||||||
uint8_t ts2068_state::port_f4_r()
|
u8 ts2068_state::port_f4_r()
|
||||||
{
|
{
|
||||||
return m_port_f4_data;
|
return m_port_f4_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ts2068_state::port_f4_w(uint8_t data)
|
void ts2068_state::port_f4_w(u8 data)
|
||||||
{
|
{
|
||||||
m_port_f4_data = data;
|
m_port_f4_data = data;
|
||||||
ts2068_update_memory();
|
ts2068_update_memory();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t tc2048_state::port_ff_r()
|
u8 tc2048_state::port_ff_r()
|
||||||
{
|
{
|
||||||
return m_port_ff_data;
|
return m_port_ff_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ts2068_state::port_ff_w(offs_t offset, uint8_t data)
|
void ts2068_state::port_ff_w(offs_t offset, u8 data)
|
||||||
{
|
{
|
||||||
/* Bits 0-2 Video Mode Select
|
/* Bits 0-2 Video Mode Select
|
||||||
Bits 3-5 64 column mode ink/paper selection
|
Bits 3-5 64 column mode ink/paper selection
|
||||||
@ -690,23 +690,21 @@ void ts2068_state::ts2068(machine_config &config)
|
|||||||
{
|
{
|
||||||
spectrum_128(config);
|
spectrum_128(config);
|
||||||
|
|
||||||
Z80(config.replace(), m_maincpu, XTAL(14'112'000)/4); /* From Schematic; 3.528 MHz */
|
Z80(config.replace(), m_maincpu, XTAL(14'112'000) / 4); /* From Schematic; 3.528 MHz */
|
||||||
m_maincpu->set_addrmap(AS_PROGRAM, &ts2068_state::ts2068_mem);
|
m_maincpu->set_addrmap(AS_PROGRAM, &ts2068_state::ts2068_mem);
|
||||||
m_maincpu->set_addrmap(AS_IO, &ts2068_state::ts2068_io);
|
m_maincpu->set_addrmap(AS_IO, &ts2068_state::ts2068_io);
|
||||||
m_maincpu->set_vblank_int("screen", FUNC(ts2068_state::spec_interrupt));
|
m_maincpu->set_vblank_int("screen", FUNC(ts2068_state::spec_interrupt));
|
||||||
config.set_maximum_quantum(attotime::from_hz(60));
|
config.set_maximum_quantum(attotime::from_hz(60));
|
||||||
|
|
||||||
/* video hardware */
|
/* video hardware */
|
||||||
|
// timings not confirmed! now same as spec128 but doubled for hires
|
||||||
|
m_screen->set_raw(XTAL(14'112'000) / 2, 456 * 2, 311, {get_screen_area().left() - TS2068_LEFT_BORDER, get_screen_area().right() + TS2068_RIGHT_BORDER, get_screen_area().top() - TS2068_TOP_BORDER, get_screen_area().bottom() + TS2068_BOTTOM_BORDER});
|
||||||
m_screen->set_refresh_hz(60);
|
m_screen->set_refresh_hz(60);
|
||||||
m_screen->set_size(TS2068_SCREEN_WIDTH, TS2068_SCREEN_HEIGHT);
|
|
||||||
m_screen->set_visarea(0, TS2068_SCREEN_WIDTH-1, 0, TS2068_SCREEN_HEIGHT-1);
|
|
||||||
m_screen->set_screen_update(FUNC(ts2068_state::screen_update));
|
|
||||||
m_screen->screen_vblank().set(FUNC(ts2068_state::screen_vblank_timex));
|
|
||||||
|
|
||||||
subdevice<gfxdecode_device>("gfxdecode")->set_info(gfx_ts2068);
|
subdevice<gfxdecode_device>("gfxdecode")->set_info(gfx_ts2068);
|
||||||
|
|
||||||
/* sound */
|
/* sound */
|
||||||
AY8912(config.replace(), "ay8912", XTAL(14'112'000)/8).add_route(ALL_OUTPUTS, "mono", 0.25); /* From Schematic; 1.764 MHz */
|
AY8912(config.replace(), "ay8912", XTAL(14'112'000) / 8).add_route(ALL_OUTPUTS, "mono", 0.25); /* From Schematic; 1.764 MHz */
|
||||||
|
|
||||||
/* cartridge */
|
/* cartridge */
|
||||||
GENERIC_CARTSLOT(config, "dockslot", generic_plain_slot, "timex_cart", "dck,bin").set_device_load(FUNC(ts2068_state::cart_load));
|
GENERIC_CARTSLOT(config, "dockslot", generic_plain_slot, "timex_cart", "dck,bin").set_device_load(FUNC(ts2068_state::cart_load));
|
||||||
@ -726,6 +724,9 @@ void ts2068_state::uk2086(machine_config &config)
|
|||||||
m_screen->set_refresh_hz(50);
|
m_screen->set_refresh_hz(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rectangle tc2048_state::get_screen_area() {
|
||||||
|
return {TS2068_LEFT_BORDER, TS2068_LEFT_BORDER + TS2068_DISPLAY_XSIZE - 1, TS2068_TOP_BORDER, TS2068_TOP_BORDER + SPEC_DISPLAY_YSIZE - 1};
|
||||||
|
}
|
||||||
|
|
||||||
void tc2048_state::tc2048(machine_config &config)
|
void tc2048_state::tc2048(machine_config &config)
|
||||||
{
|
{
|
||||||
@ -734,11 +735,9 @@ void tc2048_state::tc2048(machine_config &config)
|
|||||||
m_maincpu->set_addrmap(AS_IO, &tc2048_state::tc2048_io);
|
m_maincpu->set_addrmap(AS_IO, &tc2048_state::tc2048_io);
|
||||||
|
|
||||||
/* video hardware */
|
/* video hardware */
|
||||||
|
// timings not confirmed! now same as spec48 but doubled for hires
|
||||||
|
m_screen->set_raw(X1 / 2, 448 * 2, 312, {get_screen_area().left() - TS2068_LEFT_BORDER, get_screen_area().right() + TS2068_RIGHT_BORDER, get_screen_area().top() - TS2068_TOP_BORDER, get_screen_area().bottom() + TS2068_BOTTOM_BORDER});
|
||||||
m_screen->set_refresh_hz(50);
|
m_screen->set_refresh_hz(50);
|
||||||
m_screen->set_size(TS2068_SCREEN_WIDTH, SPEC_SCREEN_HEIGHT);
|
|
||||||
m_screen->set_visarea(0, TS2068_SCREEN_WIDTH-1, 0, SPEC_SCREEN_HEIGHT-1);
|
|
||||||
m_screen->set_screen_update(FUNC(tc2048_state::screen_update));
|
|
||||||
m_screen->screen_vblank().set(FUNC(tc2048_state::screen_vblank_timex));
|
|
||||||
|
|
||||||
/* internal ram */
|
/* internal ram */
|
||||||
m_ram->set_default_size("48K");
|
m_ram->set_default_size("48K");
|
||||||
|
@ -66,6 +66,7 @@ TODO:
|
|||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "includes/tsconf.h"
|
#include "includes/tsconf.h"
|
||||||
|
#include "cpu/z80/z80.h"
|
||||||
#include "sound/ay8910.h"
|
#include "sound/ay8910.h"
|
||||||
#include "speaker.h"
|
#include "speaker.h"
|
||||||
|
|
||||||
@ -256,11 +257,11 @@ void tsconf_state::machine_reset()
|
|||||||
void tsconf_state::tsconf(machine_config &config)
|
void tsconf_state::tsconf(machine_config &config)
|
||||||
{
|
{
|
||||||
spectrum_128(config);
|
spectrum_128(config);
|
||||||
m_maincpu->set_clock(3.5_MHz_XTAL);
|
|
||||||
|
|
||||||
config.device_remove("exp");
|
config.device_remove("exp");
|
||||||
config.device_remove("palette");
|
config.device_remove("palette");
|
||||||
|
|
||||||
|
Z80(config.replace(), m_maincpu, 14_MHz_XTAL / 4);
|
||||||
m_maincpu->set_addrmap(AS_PROGRAM, &tsconf_state::tsconf_mem);
|
m_maincpu->set_addrmap(AS_PROGRAM, &tsconf_state::tsconf_mem);
|
||||||
m_maincpu->set_addrmap(AS_IO, &tsconf_state::tsconf_io);
|
m_maincpu->set_addrmap(AS_IO, &tsconf_state::tsconf_io);
|
||||||
m_maincpu->set_addrmap(AS_OPCODES, &tsconf_state::tsconf_switch);
|
m_maincpu->set_addrmap(AS_OPCODES, &tsconf_state::tsconf_switch);
|
||||||
@ -271,7 +272,7 @@ void tsconf_state::tsconf(machine_config &config)
|
|||||||
|
|
||||||
GLUKRS(config, m_glukrs);
|
GLUKRS(config, m_glukrs);
|
||||||
|
|
||||||
TSCONF_DMA(config, m_dma, 7_MHz_XTAL);
|
TSCONF_DMA(config, m_dma, 14_MHz_XTAL / 2);
|
||||||
m_dma->in_mreq_callback().set(FUNC(tsconf_state::ram_read16));
|
m_dma->in_mreq_callback().set(FUNC(tsconf_state::ram_read16));
|
||||||
m_dma->out_mreq_callback().set(FUNC(tsconf_state::ram_write16));
|
m_dma->out_mreq_callback().set(FUNC(tsconf_state::ram_write16));
|
||||||
m_dma->in_spireq_callback().set(FUNC(tsconf_state::spi_read16));
|
m_dma->in_spireq_callback().set(FUNC(tsconf_state::spi_read16));
|
||||||
@ -293,7 +294,7 @@ void tsconf_state::tsconf(machine_config &config)
|
|||||||
.add_route(2, "rspeaker", 0.50);
|
.add_route(2, "rspeaker", 0.50);
|
||||||
|
|
||||||
PALETTE(config, "palette", FUNC(tsconf_state::tsconf_palette), 256);
|
PALETTE(config, "palette", FUNC(tsconf_state::tsconf_palette), 256);
|
||||||
m_screen->set_raw(7_MHz_XTAL, 448, with_hblank(), 448, 320, with_vblank(), 320);
|
m_screen->set_raw(14_MHz_XTAL / 2, 448, with_hblank(), 448, 320, with_vblank(), 320);
|
||||||
subdevice<gfxdecode_device>("gfxdecode")->set_info(gfx_tsconf);
|
subdevice<gfxdecode_device>("gfxdecode")->set_info(gfx_tsconf);
|
||||||
RAM(config, m_cram).set_default_size("512").set_default_value(0);
|
RAM(config, m_cram).set_default_size("512").set_default_value(0);
|
||||||
RAM(config, m_sfile).set_default_size("512").set_default_value(0); // 85*6
|
RAM(config, m_sfile).set_default_size("512").set_default_value(0); // 85*6
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
#ifndef MAME_INCLUDES_SPEC128_H
|
#ifndef MAME_INCLUDES_SPEC128_H
|
||||||
#define MAME_INCLUDES_SPEC128_H
|
#define MAME_INCLUDES_SPEC128_H
|
||||||
|
|
||||||
|
#define X1_128_AMSTRAD 35'469'000 // Main clock (Amstrad 128K model, +2A?)
|
||||||
|
#define X1_128_SINCLAIR 35.469_MHz_XTAL // Main clock (Sinclair 128K model)
|
||||||
|
|
||||||
/* 128K machines take an extra 4 cycles per scan line - add this to retrace */
|
/* 128K machines take an extra 4 cycles per scan line - add this to retrace */
|
||||||
#define SPEC128_UNSEEN_LINES 15
|
#define SPEC128_UNSEEN_LINES 15
|
||||||
#define SPEC128_RETRACE_CYCLES 52
|
#define SPEC128_RETRACE_CYCLES 52
|
||||||
|
@ -23,10 +23,7 @@
|
|||||||
|
|
||||||
/* Spectrum crystals */
|
/* Spectrum crystals */
|
||||||
|
|
||||||
#define X1 XTAL(14'000'000) // Main clock (48k Spectrum)
|
#define X1 14_MHz_XTAL // Main clock (48k Spectrum)
|
||||||
#define X1_128_AMSTRAD 35469000 // Main clock (Amstrad 128K model, +2A?)
|
|
||||||
#define X1_128_SINCLAIR 17734475 // Main clock (Sinclair 128K model)
|
|
||||||
|
|
||||||
#define X2 XTAL(4'433'619) // PAL color subcarrier
|
#define X2 XTAL(4'433'619) // PAL color subcarrier
|
||||||
|
|
||||||
/* Spectrum screen size in pixels */
|
/* Spectrum screen size in pixels */
|
||||||
@ -48,18 +45,6 @@
|
|||||||
#define SPEC_RETRACE_CYCLES 48 /* Cycles taken for horizontal retrace */
|
#define SPEC_RETRACE_CYCLES 48 /* Cycles taken for horizontal retrace */
|
||||||
#define SPEC_CYCLES_PER_LINE 224 /* Number of cycles to display a single line */
|
#define SPEC_CYCLES_PER_LINE 224 /* Number of cycles to display a single line */
|
||||||
|
|
||||||
struct EVENT_LIST_ITEM
|
|
||||||
{
|
|
||||||
/* driver defined ID for this write */
|
|
||||||
int Event_ID;
|
|
||||||
/* driver defined data for this write */
|
|
||||||
int Event_Data;
|
|
||||||
/* time at which this write occurred */
|
|
||||||
int Event_Time;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class spectrum_state : public driver_device
|
class spectrum_state : public driver_device
|
||||||
{
|
{
|
||||||
@ -100,6 +85,7 @@ public:
|
|||||||
void init_spectrum();
|
void init_spectrum();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void machine_start() override;
|
||||||
virtual void machine_reset() override;
|
virtual void machine_reset() override;
|
||||||
virtual void video_start() override;
|
virtual void video_start() override;
|
||||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param) override;
|
virtual void device_timer(emu_timer &timer, device_timer_id id, int param) override;
|
||||||
@ -113,7 +99,7 @@ protected:
|
|||||||
{
|
{
|
||||||
TIMER_IRQ_ON,
|
TIMER_IRQ_ON,
|
||||||
TIMER_IRQ_OFF,
|
TIMER_IRQ_OFF,
|
||||||
TIMER_SCANLINE
|
TIMER_SCANLINE // tsconf assumes it last know. if need more add above or fix references in clones
|
||||||
};
|
};
|
||||||
|
|
||||||
int m_port_fe_data;
|
int m_port_fe_data;
|
||||||
@ -123,28 +109,17 @@ protected:
|
|||||||
int m_port_f4_data; /* Horizontal Select Register */
|
int m_port_f4_data; /* Horizontal Select Register */
|
||||||
|
|
||||||
/* video support */
|
/* video support */
|
||||||
int m_frame_invert_count;
|
int m_frame_invert_count; /* Used for handling FLASH 1 */
|
||||||
int m_frame_number; /* Used for handling FLASH 1 */
|
|
||||||
int m_flash_invert;
|
|
||||||
optional_shared_ptr<uint8_t> m_video_ram;
|
optional_shared_ptr<uint8_t> m_video_ram;
|
||||||
uint8_t *m_screen_location;
|
uint8_t *m_screen_location;
|
||||||
|
|
||||||
int m_ROMSelection;
|
int m_ROMSelection;
|
||||||
|
|
||||||
emu_timer *m_irq_off_timer;
|
|
||||||
|
|
||||||
// Build up the screen bitmap line-by-line as the z80 uses CPU cycles.
|
// Build up the screen bitmap line-by-line as the z80 uses CPU cycles.
|
||||||
// Elimiates sprite flicker on various games (E.g. Marauder and
|
// Eliminates sprite flicker on various games (E.g. Marauder and
|
||||||
// Stormlord) and makes Firefly playable.
|
// Stormlord) and makes Firefly playable.
|
||||||
emu_timer *m_scanline_timer;
|
emu_timer *m_scanline_timer;
|
||||||
|
|
||||||
EVENT_LIST_ITEM *m_pCurrentItem;
|
|
||||||
int m_NumEvents;
|
|
||||||
int m_TotalEvents;
|
|
||||||
char *m_pEventListBuffer;
|
|
||||||
int m_LastFrameStartTime;
|
|
||||||
int m_CyclesPerLine;
|
|
||||||
|
|
||||||
uint8_t m_ram_disabled_by_beta;
|
uint8_t m_ram_disabled_by_beta;
|
||||||
uint8_t pre_opcode_fetch_r(offs_t offset);
|
uint8_t pre_opcode_fetch_r(offs_t offset);
|
||||||
void spectrum_rom_w(offs_t offset, uint8_t data);
|
void spectrum_rom_w(offs_t offset, uint8_t data);
|
||||||
@ -156,19 +131,13 @@ protected:
|
|||||||
uint8_t spectrum_ula_r(offs_t offset);
|
uint8_t spectrum_ula_r(offs_t offset);
|
||||||
void spectrum_port_w(offs_t offset, uint8_t data);
|
void spectrum_port_w(offs_t offset, uint8_t data);
|
||||||
virtual uint8_t spectrum_port_r(offs_t offset);
|
virtual uint8_t spectrum_port_r(offs_t offset);
|
||||||
virtual uint8_t floating_bus_r();
|
uint8_t floating_bus_r();
|
||||||
uint8_t spectrum_clone_port_r(offs_t offset);
|
uint8_t spectrum_clone_port_r(offs_t offset);
|
||||||
|
|
||||||
void spectrum_palette(palette_device &palette) const;
|
void spectrum_palette(palette_device &palette) const;
|
||||||
virtual uint32_t screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
virtual u32 screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||||
DECLARE_WRITE_LINE_MEMBER(screen_vblank_spectrum);
|
|
||||||
INTERRUPT_GEN_MEMBER(spec_interrupt);
|
INTERRUPT_GEN_MEMBER(spec_interrupt);
|
||||||
|
|
||||||
unsigned int m_previous_border_x, m_previous_border_y;
|
|
||||||
bitmap_ind16 m_border_bitmap;
|
|
||||||
unsigned int m_previous_screen_x, m_previous_screen_y;
|
|
||||||
bitmap_ind16 m_screen_bitmap;
|
|
||||||
|
|
||||||
DECLARE_SNAPSHOT_LOAD_MEMBER(snapshot_cb);
|
DECLARE_SNAPSHOT_LOAD_MEMBER(snapshot_cb);
|
||||||
DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb);
|
DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb);
|
||||||
|
|
||||||
@ -210,11 +179,11 @@ protected:
|
|||||||
optional_ioport m_io_joy1;
|
optional_ioport m_io_joy1;
|
||||||
optional_ioport m_io_joy2;
|
optional_ioport m_io_joy2;
|
||||||
|
|
||||||
virtual void spectrum_UpdateBorderBitmap();
|
virtual u8 get_border_color(u16 hpos = ~0, u16 vpos = ~0);
|
||||||
virtual u16 get_border_color();
|
// Defines position of main screen excluding border
|
||||||
virtual void spectrum_UpdateScreenBitmap(bool eof = false);
|
virtual rectangle get_screen_area();
|
||||||
inline unsigned char get_display_color(unsigned char color, int invert);
|
virtual void spectrum_update_border(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||||
inline void spectrum_plot_pixel(bitmap_ind16 &bitmap, int x, int y, uint32_t color);
|
virtual void spectrum_update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||||
|
|
||||||
// snapshot helpers
|
// snapshot helpers
|
||||||
void update_paging();
|
void update_paging();
|
||||||
@ -255,6 +224,7 @@ protected:
|
|||||||
virtual void machine_reset() override;
|
virtual void machine_reset() override;
|
||||||
|
|
||||||
virtual void spectrum_128_update_memory() override;
|
virtual void spectrum_128_update_memory() override;
|
||||||
|
virtual rectangle get_screen_area() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t spectrum_128_pre_opcode_fetch_r(offs_t offset);
|
uint8_t spectrum_128_pre_opcode_fetch_r(offs_t offset);
|
||||||
@ -262,7 +232,6 @@ private:
|
|||||||
uint8_t spectrum_128_bank1_r(offs_t offset);
|
uint8_t spectrum_128_bank1_r(offs_t offset);
|
||||||
void spectrum_128_port_7ffd_w(offs_t offset, uint8_t data);
|
void spectrum_128_port_7ffd_w(offs_t offset, uint8_t data);
|
||||||
virtual uint8_t spectrum_port_r(offs_t offset) override;
|
virtual uint8_t spectrum_port_r(offs_t offset) override;
|
||||||
virtual uint8_t floating_bus_r() override;
|
|
||||||
//uint8_t spectrum_128_ula_r();
|
//uint8_t spectrum_128_ula_r();
|
||||||
|
|
||||||
void spectrum_128_io(address_map &map);
|
void spectrum_128_io(address_map &map);
|
||||||
|
@ -39,17 +39,16 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void machine_reset() override;
|
virtual void machine_reset() override;
|
||||||
|
|
||||||
uint8_t port_ff_r();
|
u8 port_ff_r();
|
||||||
DECLARE_WRITE_LINE_MEMBER(screen_vblank_timex);
|
|
||||||
|
|
||||||
|
void spectrum_update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) override;
|
||||||
|
rectangle get_screen_area() override;
|
||||||
void hires_scanline(bitmap_ind16 &bitmap, int y, int borderlines);
|
void hires_scanline(bitmap_ind16 &bitmap, int y, int borderlines);
|
||||||
void _64col_scanline(bitmap_ind16 &bitmap, int y, int borderlines, unsigned short inkcolor);
|
void _64col_scanline(bitmap_ind16 &bitmap, int y, int borderlines, unsigned short inkcolor);
|
||||||
void lores_scanline(bitmap_ind16 &bitmap, int y, int borderlines, int screen);
|
void lores_scanline(bitmap_ind16 &bitmap, int y, int borderlines, int screen);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void port_ff_w(offs_t offset, uint8_t data);
|
void port_ff_w(offs_t offset, u8 data);
|
||||||
|
|
||||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
|
||||||
|
|
||||||
void tc2048_io(address_map &map);
|
void tc2048_io(address_map &map);
|
||||||
void tc2048_mem(address_map &map);
|
void tc2048_mem(address_map &map);
|
||||||
@ -84,11 +83,9 @@ private:
|
|||||||
TIMEX_CART_HOME
|
TIMEX_CART_HOME
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t port_f4_r();
|
u8 port_f4_r();
|
||||||
void port_f4_w(uint8_t data);
|
void port_f4_w(u8 data);
|
||||||
void port_ff_w(offs_t offset, uint8_t data);
|
void port_ff_w(offs_t offset, u8 data);
|
||||||
|
|
||||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
|
||||||
|
|
||||||
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load);
|
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load);
|
||||||
int m_dock_cart_type, m_ram_chunks;
|
int m_dock_cart_type, m_ram_chunks;
|
||||||
|
@ -144,17 +144,15 @@ private:
|
|||||||
template <u8 Layer>
|
template <u8 Layer>
|
||||||
TILE_GET_INFO_MEMBER(get_tile_info_16c);
|
TILE_GET_INFO_MEMBER(get_tile_info_16c);
|
||||||
|
|
||||||
// Changing this consider to revert 'virtual' in spectrum.h
|
u8 get_border_color(u16 hpos = ~0, u16 vpos = ~0) override;
|
||||||
u32 screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) override;
|
rectangle get_screen_area() override;
|
||||||
void spectrum_UpdateScreenBitmap(bool eof = false) override;
|
void spectrum_update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) override;
|
||||||
void spectrum_UpdateBorderBitmap() override;
|
void tsconf_UpdateZxScreenBitmap(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||||
void spectrum_UpdateZxScreenBitmap();
|
void tsconf_UpdateTxtBitmap(bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||||
void tsconf_UpdateTxtBitmap(unsigned int from_x, unsigned int from_y);
|
void tsconf_UpdateGfxBitmap(bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||||
void tsconf_UpdateGfxBitmap(unsigned int from_x, unsigned int from_y);
|
void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||||
void tsconf_palette(palette_device &palette) const;
|
void tsconf_palette(palette_device &palette) const;
|
||||||
void draw_sprites(const rectangle &cliprect);
|
|
||||||
void tsconf_update_video_mode();
|
void tsconf_update_video_mode();
|
||||||
rectangle get_screen_area();
|
|
||||||
|
|
||||||
void tsconf_port_7ffd_w(u8 data);
|
void tsconf_port_7ffd_w(u8 data);
|
||||||
void tsconf_ula_w(offs_t offset, u8 data);
|
void tsconf_ula_w(offs_t offset, u8 data);
|
||||||
@ -209,13 +207,12 @@ private:
|
|||||||
gluk_ext m_port_f7_ext;
|
gluk_ext m_port_f7_ext;
|
||||||
u8 m_port_f7_gluk_reg;
|
u8 m_port_f7_gluk_reg;
|
||||||
|
|
||||||
u16 m_rendering_gfx_y_offset;
|
s16 m_gfx_y_frame_offset;
|
||||||
required_device<device_palette_interface> m_palette;
|
required_device<device_palette_interface> m_palette;
|
||||||
required_device<gfxdecode_device> m_gfxdecode;
|
required_device<gfxdecode_device> m_gfxdecode;
|
||||||
tilemap_t *m_ts_tilemap[3];
|
tilemap_t *m_ts_tilemap[3];
|
||||||
required_device<ram_device> m_cram;
|
required_device<ram_device> m_cram;
|
||||||
required_device<ram_device> m_sfile;
|
required_device<ram_device> m_sfile;
|
||||||
u16 m_previous_tsu_vpos;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*----------- defined in drivers/tsconf.c -----------*/
|
/*----------- defined in drivers/tsconf.c -----------*/
|
||||||
|
@ -400,9 +400,11 @@ void spectrum_state::setup_sp(uint8_t *snapdata, uint32_t snapsize)
|
|||||||
m_maincpu->set_input_line(INPUT_LINE_IRQ0, intr);
|
m_maincpu->set_input_line(INPUT_LINE_IRQ0, intr);
|
||||||
m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
|
m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
|
||||||
|
|
||||||
|
/* Not supported as it's wrong anyway: even if we define current invert it can change to opposite either on next frame or N frames later depending on current state.
|
||||||
data = BIT(status, 5);
|
data = BIT(status, 5);
|
||||||
m_flash_invert = data;
|
m_flash_invert = data;
|
||||||
logerror("FLASH state: %s\n", data ? "PAPER on INK" : "INK on PAPER");
|
logerror("FLASH state: %s\n", data ? "PAPER on INK" : "INK on PAPER");
|
||||||
|
*/
|
||||||
|
|
||||||
// Memory dump
|
// Memory dump
|
||||||
logerror("Loading %04X bytes of RAM at %04X\n", size, start);
|
logerror("Loading %04X bytes of RAM at %04X\n", size, start);
|
||||||
|
@ -50,9 +50,7 @@ rectangle tsconf_state::get_screen_area()
|
|||||||
{
|
{
|
||||||
rectangle info = screen_area[BIT(m_regs[V_CONFIG], 6, 2)];
|
rectangle info = screen_area[BIT(m_regs[V_CONFIG], 6, 2)];
|
||||||
if (VM == VM_TXT)
|
if (VM == VM_TXT)
|
||||||
{
|
|
||||||
info.set_width(info.width() << 1);
|
info.set_width(info.width() << 1);
|
||||||
}
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,183 +105,14 @@ void tsconf_state::tsconf_update_video_mode()
|
|||||||
m_screen->configure(visarea.max_x + 1, visarea.max_y + 1, visarea, m_screen->frame_period().as_attoseconds());
|
m_screen->configure(visarea.max_x + 1, visarea.max_y + 1, visarea, m_screen->frame_period().as_attoseconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t tsconf_state::screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
u8 tsconf_state::get_border_color(u16 hpos, u16 vpos)
|
||||||
{
|
{
|
||||||
return 0;
|
return m_regs[BORDER];
|
||||||
}
|
|
||||||
|
|
||||||
void to_display(rectangle area, unsigned int &x, unsigned int &y)
|
|
||||||
{
|
|
||||||
if (y < area.top() || y > area.bottom())
|
|
||||||
{
|
|
||||||
x = area.left();
|
|
||||||
y = area.top();
|
|
||||||
}
|
|
||||||
else if (x < area.left())
|
|
||||||
x = area.left();
|
|
||||||
else if (x > area.right())
|
|
||||||
{
|
|
||||||
x = area.left();
|
|
||||||
to_display(area, x, ++y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsconf_state::spectrum_UpdateZxScreenBitmap()
|
|
||||||
{
|
|
||||||
unsigned int to_x = m_screen->hpos();
|
|
||||||
unsigned int to_y = m_screen->vpos();
|
|
||||||
to_display(m_screen->visible_area(), to_x, to_y);
|
|
||||||
|
|
||||||
if ((m_previous_screen_x == to_x) && (m_previous_screen_y == to_y))
|
|
||||||
return;
|
|
||||||
|
|
||||||
bitmap_ind16 *bm = &m_screen->curbitmap().as_ind16();
|
|
||||||
if (bm->valid())
|
|
||||||
{
|
|
||||||
u8 pal_offset = m_regs[PAL_SEL] << 4;
|
|
||||||
u16 border_color = m_regs[BORDER];
|
|
||||||
bool border_only = VM != VM_ZX || BIT(m_regs[V_CONFIG], 5);
|
|
||||||
rectangle screen = screen_area[0];
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (border_only || !screen.contains(m_previous_screen_x, m_previous_screen_y))
|
|
||||||
bm->pix(m_previous_screen_y, m_previous_screen_x) = border_color;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u16 x = m_previous_screen_x - screen.left();
|
|
||||||
if ((x & 7) == 0)
|
|
||||||
{
|
|
||||||
u16 y = m_previous_screen_y - screen.top();
|
|
||||||
u16 *pix = &bm->pix(m_previous_screen_y, m_previous_screen_x);
|
|
||||||
u8 attr = *(m_ram->pointer() + PAGE4K(m_regs[V_PAGE]) + ((y & 0xF8) << 2) + (x >> 3) + 0x1800);
|
|
||||||
u8 scr = *(m_ram->pointer() + PAGE4K(m_regs[V_PAGE]) + ((y & 7) << 8) + ((y & 0x38) << 2) + ((y & 0xC0) << 5) + (x >> 3));
|
|
||||||
u16 ink = ((attr & 0x07) + ((attr >> 3) & 0x08)) | pal_offset;
|
|
||||||
u16 pap = ((attr >> 3) & 0x0f) | pal_offset;
|
|
||||||
|
|
||||||
if (m_flash_invert && (attr & 0x80))
|
|
||||||
scr = ~scr;
|
|
||||||
|
|
||||||
for (uint8_t b = 0x80; b != 0; b >>= 1)
|
|
||||||
*pix++ = (scr & b) ? ink : pap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
to_display(m_screen->visible_area(), ++m_previous_screen_x, m_previous_screen_y);
|
|
||||||
} while (!((m_previous_screen_x == to_x) && (m_previous_screen_y == to_y)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsconf_state::tsconf_UpdateTxtBitmap(unsigned int from_x, unsigned int from_y)
|
|
||||||
{
|
|
||||||
unsigned int to_x = m_screen->hpos();
|
|
||||||
unsigned int to_y = m_screen->vpos();
|
|
||||||
rectangle screen = get_screen_area();
|
|
||||||
to_display(screen, to_x, to_y);
|
|
||||||
|
|
||||||
u8 pal_offset = m_regs[PAL_SEL] << 4;
|
|
||||||
while (!((from_x == to_x) && (from_y == to_y)))
|
|
||||||
{
|
|
||||||
if (from_x == screen.left() && (from_y == screen.top()))
|
|
||||||
m_rendering_gfx_y_offset = OFFS_512(G_Y_OFFS_L);
|
|
||||||
|
|
||||||
u16 x = from_x - screen.left();
|
|
||||||
u16 *bm = &m_screen->curbitmap().as_ind16().pix(from_y, from_x);
|
|
||||||
s16 width = (screen.width() - x) / 8;
|
|
||||||
|
|
||||||
// TODO u16 x_offset = OFFS_512(G_X_OFFS_L);
|
|
||||||
u8 *font_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE] ^ 0x01);
|
|
||||||
u8 *text_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE]) + (m_rendering_gfx_y_offset / 8 * 256 + x / 8);
|
|
||||||
for (; width > 0; width--)
|
|
||||||
{
|
|
||||||
u8 char_x = *(font_location + (*text_location * 8) + (m_rendering_gfx_y_offset % 8));
|
|
||||||
u8 font_color = *(text_location + 128) & 0x0f;
|
|
||||||
u8 bg_color = (*(text_location + 128) & 0xf0) >> 4;
|
|
||||||
for (auto i = 7; i >= 0; i--)
|
|
||||||
*bm++ = (BIT(char_x, i) ? font_color : bg_color) | pal_offset;
|
|
||||||
text_location++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from_y == to_y)
|
|
||||||
// done - scanline updated partially
|
|
||||||
from_x = to_x;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
from_y += 1;
|
|
||||||
m_rendering_gfx_y_offset = (m_rendering_gfx_y_offset + 1) & 0x1ff;
|
|
||||||
from_x = screen.left();
|
|
||||||
to_display(screen, from_x, from_y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsconf_state::tsconf_UpdateGfxBitmap(unsigned int from_x, unsigned int from_y)
|
|
||||||
{
|
|
||||||
unsigned int to_x = m_screen->hpos();
|
|
||||||
unsigned int to_y = m_screen->vpos();
|
|
||||||
rectangle screen = get_screen_area();
|
|
||||||
to_display(screen, to_x, to_y);
|
|
||||||
|
|
||||||
u8 pal_offset = m_regs[PAL_SEL] << 4;
|
|
||||||
while (!((from_x == to_x) && (from_y == to_y)))
|
|
||||||
{
|
|
||||||
if (from_x == screen.left() && (from_y == screen.top()))
|
|
||||||
m_rendering_gfx_y_offset = OFFS_512(G_Y_OFFS_L);
|
|
||||||
|
|
||||||
u16 x = from_x - screen.left();
|
|
||||||
u16 x_offset = (OFFS_512(G_X_OFFS_L) + x) & 0x1ff;
|
|
||||||
u16 *bm = &m_screen->curbitmap().as_ind16().pix(from_y, from_x);
|
|
||||||
u8 *video_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE]) + ((m_rendering_gfx_y_offset * 512 + x_offset) >> (2 - VM));
|
|
||||||
s16 width = screen.width() - x;
|
|
||||||
if (VM == VM_16C)
|
|
||||||
{
|
|
||||||
if (x_offset & 1)
|
|
||||||
{
|
|
||||||
*bm++ = (*video_location++ & 0x0f) | pal_offset;
|
|
||||||
x_offset++;
|
|
||||||
width--;
|
|
||||||
}
|
|
||||||
for (; width > 0; width -= 2)
|
|
||||||
{
|
|
||||||
if (x_offset == 512)
|
|
||||||
video_location -= 256;
|
|
||||||
u8 pix = *video_location++;
|
|
||||||
*bm++ = (pix >> 4) | pal_offset;
|
|
||||||
if (width == 1)
|
|
||||||
x_offset++;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*bm++ = (pix & 0x0f) | pal_offset;
|
|
||||||
x_offset += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // VM_256C
|
|
||||||
{
|
|
||||||
for (; width > 0; width--)
|
|
||||||
{
|
|
||||||
if (x_offset == 512)
|
|
||||||
video_location -= 512;
|
|
||||||
*bm++ = *video_location++;
|
|
||||||
x_offset++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from_y == to_y)
|
|
||||||
// done - scanline updated partially
|
|
||||||
from_x = to_x;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
from_y += 1;
|
|
||||||
m_rendering_gfx_y_offset = (m_rendering_gfx_y_offset + 1) & 0x1ff;
|
|
||||||
from_x = screen.left();
|
|
||||||
to_display(screen, from_x, from_y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Layered as:
|
Layered as:
|
||||||
+ Border
|
+ Border - already updated with screen_update_spectrum()
|
||||||
+ Graphics
|
+ Graphics
|
||||||
+ Sprites 0
|
+ Sprites 0
|
||||||
+ Tiles 0
|
+ Tiles 0
|
||||||
@ -291,70 +120,135 @@ Layered as:
|
|||||||
+ Tiles 1
|
+ Tiles 1
|
||||||
+ Sprites 2
|
+ Sprites 2
|
||||||
*/
|
*/
|
||||||
void tsconf_state::spectrum_UpdateScreenBitmap(bool eof)
|
void tsconf_state::spectrum_update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||||
{
|
{
|
||||||
rectangle screen = get_screen_area();
|
if (!BIT(m_regs[V_CONFIG], 5))
|
||||||
unsigned int from_x = m_previous_screen_x;
|
|
||||||
unsigned int from_y = m_previous_screen_y;
|
|
||||||
|
|
||||||
spectrum_UpdateZxScreenBitmap();
|
|
||||||
if (!BIT(m_regs[V_CONFIG], 5) && VM != VM_ZX)
|
|
||||||
{
|
{
|
||||||
to_display(screen, from_x, from_y);
|
if (VM == VM_ZX)
|
||||||
if (VM == VM_TXT)
|
tsconf_UpdateZxScreenBitmap(screen, bitmap, cliprect);
|
||||||
tsconf_UpdateTxtBitmap(from_x, from_y);
|
else if (VM == VM_TXT)
|
||||||
|
tsconf_UpdateTxtBitmap(bitmap, cliprect);
|
||||||
else
|
else
|
||||||
tsconf_UpdateGfxBitmap(from_x, from_y);
|
tsconf_UpdateGfxBitmap(bitmap, cliprect);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bitmap.fill(get_border_color(), cliprect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!BIT(m_regs[V_CONFIG], 4))
|
if (!BIT(m_regs[V_CONFIG], 4))
|
||||||
{
|
{
|
||||||
if (m_screen->vpos() == m_previous_tsu_vpos)
|
screen.priority().fill(0, cliprect);
|
||||||
return;
|
|
||||||
|
|
||||||
bool draw = false;
|
|
||||||
s16 y = m_screen->vpos() - screen.top();
|
|
||||||
if (m_screen->vpos() == screen.bottom())
|
|
||||||
{
|
|
||||||
m_previous_tsu_vpos = screen.top();
|
|
||||||
screen.min_y = m_previous_tsu_vpos;
|
|
||||||
draw = true;
|
|
||||||
}
|
|
||||||
else if (y >= 0 && y < screen.height())
|
|
||||||
{
|
|
||||||
// Update unrendered above excluding current line.
|
|
||||||
screen.sety(m_previous_tsu_vpos, m_screen->vpos() - 1);
|
|
||||||
// Too expencive to draw every line. Batch 8+ for now.
|
|
||||||
draw = screen.height() > 7;
|
|
||||||
if (!draw && (screen.bottom() + 1) == get_screen_area().bottom())
|
|
||||||
{
|
|
||||||
screen.max_y++;
|
|
||||||
draw = true;
|
|
||||||
}
|
|
||||||
if (draw)
|
|
||||||
m_previous_tsu_vpos = m_screen->vpos();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (draw)
|
|
||||||
{
|
|
||||||
m_screen->priority().fill(0, screen);
|
|
||||||
if (BIT(m_regs[TS_CONFIG], 5))
|
if (BIT(m_regs[TS_CONFIG], 5))
|
||||||
m_ts_tilemap[TM_TILES0]->draw(*m_screen, m_screen->curbitmap().as_ind16(), screen,
|
m_ts_tilemap[TM_TILES0]->draw(screen, bitmap, cliprect,
|
||||||
BIT(m_regs[TS_CONFIG], 2) ? TILEMAP_DRAW_ALL_CATEGORIES : TILEMAP_DRAW_CATEGORY(1), 1);
|
BIT(m_regs[TS_CONFIG], 2) ? TILEMAP_DRAW_ALL_CATEGORIES : TILEMAP_DRAW_CATEGORY(1), 1);
|
||||||
|
|
||||||
if (BIT(m_regs[TS_CONFIG], 6))
|
if (BIT(m_regs[TS_CONFIG], 6))
|
||||||
m_ts_tilemap[TM_TILES1]->draw(*m_screen, m_screen->curbitmap().as_ind16(), screen,
|
m_ts_tilemap[TM_TILES1]->draw(screen, bitmap, cliprect,
|
||||||
BIT(m_regs[TS_CONFIG], 3) ? TILEMAP_DRAW_ALL_CATEGORIES : TILEMAP_DRAW_CATEGORY(1), 2);
|
BIT(m_regs[TS_CONFIG], 3) ? TILEMAP_DRAW_ALL_CATEGORIES : TILEMAP_DRAW_CATEGORY(1), 2);
|
||||||
|
|
||||||
if (BIT(m_regs[TS_CONFIG], 7))
|
if (BIT(m_regs[TS_CONFIG], 7))
|
||||||
draw_sprites(screen);
|
{
|
||||||
|
// draw_sprites(screen, bitmap, cliprect);
|
||||||
|
// Avoid frequent expensive updates for now. Currently once per frame
|
||||||
|
if (cliprect.bottom() == get_screen_area().bottom() && cliprect.right() == get_screen_area().right())
|
||||||
|
draw_sprites(screen, bitmap, get_screen_area());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tsconf_state::spectrum_UpdateBorderBitmap()
|
void tsconf_state::tsconf_UpdateZxScreenBitmap(screen_device &screen_d, bitmap_ind16 &bitmap, const rectangle &screen)
|
||||||
{
|
{
|
||||||
spectrum_UpdateScreenBitmap();
|
u8 pal_offset = m_regs[PAL_SEL] << 4;
|
||||||
|
u8 *screen_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE]);
|
||||||
|
u8 *attrs_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE]) + 0x1800;
|
||||||
|
bool invert_attrs = u64(screen_d.frame_number() / m_frame_invert_count) & 1;
|
||||||
|
for (u16 vpos = screen.top(); vpos <= screen.bottom(); vpos++)
|
||||||
|
{
|
||||||
|
u16 hpos = screen.left();
|
||||||
|
u16 x = hpos - get_screen_area().left();
|
||||||
|
u16 y = vpos - get_screen_area().top();
|
||||||
|
u8 *scr = &screen_location[((y & 7) << 8) | ((y & 0x38) << 2) | ((y & 0xc0) << 5) | (x >> 3)];
|
||||||
|
u8 *attr = &attrs_location[((y & 0xf8) << 2) | (x >> 3)];
|
||||||
|
u16 *pix = &(bitmap.pix(vpos, hpos));
|
||||||
|
while (hpos <= screen.right())
|
||||||
|
{
|
||||||
|
u16 ink = pal_offset | ((*attr >> 3) & 0x08) | (*attr & 0x07);
|
||||||
|
u16 pap = pal_offset | ((*attr >> 3) & 0x0f);
|
||||||
|
u8 pix8 = (invert_attrs && (*attr & 0x80)) ? ~*scr : *scr;
|
||||||
|
|
||||||
|
for (u8 b = 0x80 >> (x & 0x07); b != 0 && hpos <= screen.right(); b >>= 1, x++, hpos++)
|
||||||
|
*pix++ = (pix8 & b) ? ink : pap;
|
||||||
|
scr++;
|
||||||
|
attr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tsconf_state::tsconf_UpdateTxtBitmap(bitmap_ind16 &bitmap, const rectangle &screen)
|
||||||
|
{
|
||||||
|
u8 *font_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE] ^ 0x01);
|
||||||
|
u8 pal_offset = m_regs[PAL_SEL] << 4;
|
||||||
|
for (u16 vpos = screen.top(); vpos <= screen.bottom(); vpos++)
|
||||||
|
{
|
||||||
|
u16 hpos = screen.left();
|
||||||
|
u16 x = hpos - get_screen_area().left();
|
||||||
|
u16 y = vpos - get_screen_area().top();
|
||||||
|
u16 y_offset = (OFFS_512(G_Y_OFFS_L) + y) & 0x1ff;
|
||||||
|
|
||||||
|
// TODO? u16 x_offset = OFFS_512(G_X_OFFS_L);
|
||||||
|
u8 *text_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE]) + (y_offset / 8 * 256 + x / 8);
|
||||||
|
u16 *pix = &(bitmap.pix(vpos, hpos));
|
||||||
|
while (hpos <= screen.right())
|
||||||
|
{
|
||||||
|
u8 font_color = *(text_location + 128) & 0x0f;
|
||||||
|
u8 bg_color = (*(text_location + 128) & 0xf0) >> 4;
|
||||||
|
u8 char_x = *(font_location + (*text_location * 8) + (y_offset % 8));
|
||||||
|
for (u8 b = 0x80 >> (x & 0x07); b != 0 && hpos <= screen.right(); b >>= 1, x++, hpos++)
|
||||||
|
*pix++ = pal_offset | ((char_x & b) ? font_color : bg_color);
|
||||||
|
text_location++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tsconf_state::tsconf_UpdateGfxBitmap(bitmap_ind16 &bitmap, const rectangle &screen)
|
||||||
|
{
|
||||||
|
u8 pal_offset = m_regs[PAL_SEL] << 4;
|
||||||
|
for (u16 vpos = screen.top(); vpos <= screen.bottom(); vpos++)
|
||||||
|
{
|
||||||
|
u16 y_offset = (0x200 + OFFS_512(G_Y_OFFS_L) + m_gfx_y_frame_offset + (vpos - get_screen_area().top())) & 0x1ff;
|
||||||
|
u16 x_offset = (OFFS_512(G_X_OFFS_L) + (screen.left() - get_screen_area().left())) & 0x1ff;
|
||||||
|
u8 *video_location = m_ram->pointer() + PAGE4K(m_regs[V_PAGE]) + ((y_offset * 512 + x_offset) >> (2 - VM));
|
||||||
|
u16 *bm = &(bitmap.pix(vpos, screen.left()));
|
||||||
|
s16 width = screen.width();
|
||||||
|
if (VM == VM_16C)
|
||||||
|
{
|
||||||
|
if (x_offset & 1)
|
||||||
|
{
|
||||||
|
*bm++ = pal_offset | (*video_location++ & 0x0f);
|
||||||
|
x_offset++;
|
||||||
|
width--;
|
||||||
|
}
|
||||||
|
for (; width > 0; width -= 2, x_offset += 2)
|
||||||
|
{
|
||||||
|
if (x_offset == 512)
|
||||||
|
video_location -= 256;
|
||||||
|
u8 pix = *video_location++;
|
||||||
|
*bm++ = pal_offset | (pix >> 4);
|
||||||
|
if (width != 1)
|
||||||
|
*bm++ = pal_offset | (pix & 0x0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // VM_256C
|
||||||
|
{
|
||||||
|
for (; width > 0; width--, x_offset++)
|
||||||
|
{
|
||||||
|
if (x_offset == 512)
|
||||||
|
video_location -= 512;
|
||||||
|
*bm++ = *video_location++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -366,7 +260,7 @@ SFILE Reg.16 7 6 5 4 3 2 1 0
|
|||||||
4 R2L TNUM[7:0]
|
4 R2L TNUM[7:0]
|
||||||
5 R2H SPAL[7:4] TNUM[11:8]
|
5 R2H SPAL[7:4] TNUM[11:8]
|
||||||
*/
|
*/
|
||||||
void tsconf_state::draw_sprites(const rectangle &cliprect)
|
void tsconf_state::draw_sprites(screen_device &screen_d, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||||
{
|
{
|
||||||
rectangle screen = get_screen_area();
|
rectangle screen = get_screen_area();
|
||||||
|
|
||||||
@ -415,7 +309,7 @@ void tsconf_state::draw_sprites(const rectangle &cliprect)
|
|||||||
u8 tile_col = (code % 64) + flipx * width8;
|
u8 tile_col = (code % 64) + flipx * width8;
|
||||||
for (auto ix = x; ix <= x + width8 * 8; ix = ix + 8)
|
for (auto ix = x; ix <= x + width8 * 8; ix = ix + 8)
|
||||||
{
|
{
|
||||||
m_gfxdecode->gfx(TM_SPRITES)->prio_transpen(m_screen->curbitmap().as_ind16(), cliprect, tmp_tile_oversized_to_code((tile_row % 64) * 64 + (tile_col % 64)), pal, flipx, flipy, ix, iy, m_screen->priority(), pmask, 0);
|
m_gfxdecode->gfx(TM_SPRITES)->prio_transpen(bitmap, cliprect, tmp_tile_oversized_to_code((tile_row % 64) * 64 + (tile_col % 64)), pal, flipx, flipy, ix, iy, screen_d.priority(), pmask, 0);
|
||||||
tile_col += flipx ? -1 : 1;
|
tile_col += flipx ? -1 : 1;
|
||||||
}
|
}
|
||||||
tile_row += flipy ? -1 : 1;
|
tile_row += flipy ? -1 : 1;
|
||||||
@ -600,7 +494,7 @@ void tsconf_state::tsconf_port_xxaf_w(offs_t port, u8 data)
|
|||||||
{
|
{
|
||||||
case BORDER:
|
case BORDER:
|
||||||
if (val_changed)
|
if (val_changed)
|
||||||
spectrum_UpdateScreenBitmap();
|
m_screen->update_now();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -751,13 +645,9 @@ u8 tsconf_state::tsconf_port_f7_r(offs_t offset)
|
|||||||
// BFF7
|
// BFF7
|
||||||
u8 data = 0xff;
|
u8 data = 0xff;
|
||||||
if (m_port_f7_ext == PS2KEYBOARDS_LOG && m_port_f7_gluk_reg == 0xf0)
|
if (m_port_f7_ext == PS2KEYBOARDS_LOG && m_port_f7_gluk_reg == 0xf0)
|
||||||
{
|
|
||||||
data = m_keyboard->read();
|
data = m_keyboard->read();
|
||||||
}
|
|
||||||
else if (m_port_f7_ext != DISABLED)
|
else if (m_port_f7_ext != DISABLED)
|
||||||
{
|
|
||||||
data = m_glukrs->read(m_port_f7_gluk_reg);
|
data = m_glukrs->read(m_port_f7_gluk_reg);
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -854,14 +744,12 @@ void tsconf_state::update_frame_timer()
|
|||||||
u16 vpos = OFFS_512(VS_INT_L);
|
u16 vpos = OFFS_512(VS_INT_L);
|
||||||
u16 hpos = m_regs[HS_INT];
|
u16 hpos = m_regs[HS_INT];
|
||||||
if (hpos > 0 && vpos <= 319 && hpos <= 223)
|
if (hpos > 0 && vpos <= 319 && hpos <= 223)
|
||||||
{
|
|
||||||
// Only if not overlapping with scanline. Otherwise we need to prioritize.
|
// Only if not overlapping with scanline. Otherwise we need to prioritize.
|
||||||
m_frame_irq_timer->adjust(m_screen->time_until_pos(vpos, hpos << 1));
|
m_frame_irq_timer->adjust(m_screen->time_until_pos(vpos, hpos << 1));
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
m_frame_irq_timer->adjust(attotime::never);
|
m_frame_irq_timer->adjust(attotime::never);
|
||||||
}
|
|
||||||
|
m_gfx_y_frame_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERRUPT_GEN_MEMBER(tsconf_state::tsconf_vblank_interrupt)
|
INTERRUPT_GEN_MEMBER(tsconf_state::tsconf_vblank_interrupt)
|
||||||
@ -875,7 +763,7 @@ void tsconf_state::dma_ready(int line)
|
|||||||
if (BIT(m_regs[INT_MASK], 4))
|
if (BIT(m_regs[INT_MASK], 4))
|
||||||
{
|
{
|
||||||
m_maincpu->set_input_line_and_vector(line, ASSERT_LINE, 0xfb);
|
m_maincpu->set_input_line_and_vector(line, ASSERT_LINE, 0xfb);
|
||||||
m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))));
|
timer_set(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))), TIMER_IRQ_OFF, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -888,12 +776,27 @@ void tsconf_state::device_timer(emu_timer &timer, device_timer_id id, int param)
|
|||||||
if (BIT(m_regs[INT_MASK], 0))
|
if (BIT(m_regs[INT_MASK], 0))
|
||||||
{
|
{
|
||||||
m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xff);
|
m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xff);
|
||||||
m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))));
|
timer_set(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))), TIMER_IRQ_OFF, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TIMER_IRQ_SCANLINE:
|
case TIMER_IRQ_SCANLINE:
|
||||||
{
|
{
|
||||||
|
u16 screen_vpos = m_screen->vpos();
|
||||||
|
m_line_irq_timer->adjust(m_screen->time_until_pos(screen_vpos + 1));
|
||||||
|
if (BIT(m_regs[INT_MASK], 1))
|
||||||
|
{
|
||||||
|
m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xfd);
|
||||||
|
// Not quite precise. Scanline can't be skipped.
|
||||||
|
timer_set(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))), TIMER_IRQ_OFF, 0);
|
||||||
|
}
|
||||||
|
if (BIT(m_regs[INT_MASK], 0) && OFFS_512(VS_INT_L) == screen_vpos && m_regs[HS_INT] == 0)
|
||||||
|
{
|
||||||
|
m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xff);
|
||||||
|
timer_set(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))), TIMER_IRQ_OFF, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_screen->update_now();
|
||||||
for (const auto &[reg, val] : m_scanline_delayed_regs_update)
|
for (const auto &[reg, val] : m_scanline_delayed_regs_update)
|
||||||
{
|
{
|
||||||
m_regs[reg] = val;
|
m_regs[reg] = val;
|
||||||
@ -901,7 +804,7 @@ void tsconf_state::device_timer(emu_timer &timer, device_timer_id id, int param)
|
|||||||
{
|
{
|
||||||
case G_Y_OFFS_L:
|
case G_Y_OFFS_L:
|
||||||
case G_Y_OFFS_H:
|
case G_Y_OFFS_H:
|
||||||
m_rendering_gfx_y_offset = OFFS_512(G_Y_OFFS_L);
|
m_gfx_y_frame_offset = get_screen_area().top() - m_screen->vpos();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -909,21 +812,6 @@ void tsconf_state::device_timer(emu_timer &timer, device_timer_id id, int param)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_scanline_delayed_regs_update.clear();
|
m_scanline_delayed_regs_update.clear();
|
||||||
|
|
||||||
u16 screen_vpos = m_screen->vpos();
|
|
||||||
m_line_irq_timer->adjust(m_screen->time_until_pos(screen_vpos + 1));
|
|
||||||
if (BIT(m_regs[INT_MASK], 1))
|
|
||||||
{
|
|
||||||
m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xfd);
|
|
||||||
// Not quite precise. Scanline can't be skipped.
|
|
||||||
m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))));
|
|
||||||
}
|
|
||||||
if (BIT(m_regs[INT_MASK], 0) && OFFS_512(VS_INT_L) == screen_vpos && m_regs[HS_INT] == 0)
|
|
||||||
{
|
|
||||||
m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xff);
|
|
||||||
m_irq_off_timer->adjust(m_maincpu->clocks_to_attotime(32 * (1 << (m_regs[SYS_CONFIG] & 0x03))));
|
|
||||||
}
|
|
||||||
spectrum_UpdateScreenBitmap();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -25,79 +25,17 @@
|
|||||||
void spectrum_state::video_start()
|
void spectrum_state::video_start()
|
||||||
{
|
{
|
||||||
m_frame_invert_count = 16;
|
m_frame_invert_count = 16;
|
||||||
m_frame_number = 0;
|
|
||||||
m_flash_invert = 0;
|
|
||||||
|
|
||||||
m_previous_border_x = 0;
|
|
||||||
m_previous_border_y = 0;
|
|
||||||
m_screen->register_screen_bitmap(m_border_bitmap);
|
|
||||||
m_previous_screen_x = 0;
|
|
||||||
m_previous_screen_y = 0;
|
|
||||||
m_screen->register_screen_bitmap(m_screen_bitmap);
|
|
||||||
|
|
||||||
m_screen_location = m_video_ram;
|
m_screen_location = m_video_ram;
|
||||||
|
|
||||||
m_irq_off_timer = timer_alloc(TIMER_IRQ_OFF);
|
|
||||||
|
|
||||||
m_CyclesPerLine = SPEC_CYCLES_PER_LINE;
|
|
||||||
m_scanline_timer = timer_alloc(TIMER_SCANLINE);
|
m_scanline_timer = timer_alloc(TIMER_SCANLINE);
|
||||||
m_scanline_timer->adjust(m_maincpu->cycles_to_attotime(m_CyclesPerLine));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void spectrum_128_state::video_start()
|
void spectrum_128_state::video_start()
|
||||||
{
|
{
|
||||||
m_frame_invert_count = 16;
|
m_frame_invert_count = 16;
|
||||||
m_frame_number = 0;
|
|
||||||
m_flash_invert = 0;
|
|
||||||
|
|
||||||
m_previous_border_x = 0;
|
|
||||||
m_previous_border_y = 0;
|
|
||||||
m_screen->register_screen_bitmap(m_border_bitmap);
|
|
||||||
m_previous_screen_x = 0;
|
|
||||||
m_previous_screen_y = 0;
|
|
||||||
m_screen->register_screen_bitmap(m_screen_bitmap);
|
|
||||||
|
|
||||||
m_screen_location = m_ram->pointer() + (5 << 14);
|
m_screen_location = m_ram->pointer() + (5 << 14);
|
||||||
|
|
||||||
m_irq_off_timer = timer_alloc(TIMER_IRQ_OFF);
|
|
||||||
|
|
||||||
m_CyclesPerLine = SPEC128_CYCLES_PER_LINE;
|
|
||||||
m_scanline_timer = timer_alloc(TIMER_SCANLINE);
|
m_scanline_timer = timer_alloc(TIMER_SCANLINE);
|
||||||
m_scanline_timer->adjust(m_maincpu->cycles_to_attotime(m_CyclesPerLine));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* return the color to be used inverting FLASHing colors if necessary */
|
|
||||||
inline unsigned char spectrum_state::get_display_color (unsigned char color, int invert)
|
|
||||||
{
|
|
||||||
if (invert && (color & 0x80))
|
|
||||||
return (color & 0xc0) + ((color & 0x38) >> 3) + ((color & 0x07) << 3);
|
|
||||||
else
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Code to change the FLASH status every 25 frames. Note this must be
|
|
||||||
independent of frame skip etc. */
|
|
||||||
WRITE_LINE_MEMBER(spectrum_state::screen_vblank_spectrum)
|
|
||||||
{
|
|
||||||
// rising edge
|
|
||||||
if (state)
|
|
||||||
{
|
|
||||||
spectrum_UpdateBorderBitmap();
|
|
||||||
spectrum_UpdateScreenBitmap(true);
|
|
||||||
|
|
||||||
m_frame_number++;
|
|
||||||
|
|
||||||
if (m_frame_number >= m_frame_invert_count)
|
|
||||||
{
|
|
||||||
m_frame_number = 0;
|
|
||||||
m_flash_invert = !m_flash_invert;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
Update the spectrum screen display.
|
Update the spectrum screen display.
|
||||||
|
|
||||||
@ -121,72 +59,6 @@ WRITE_LINE_MEMBER(spectrum_state::screen_vblank_spectrum)
|
|||||||
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
inline void spectrum_state::spectrum_plot_pixel(bitmap_ind16 &bitmap, int x, int y, uint32_t color)
|
|
||||||
{
|
|
||||||
bitmap.pix(y, x) = (uint16_t)color;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t spectrum_state::screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
|
||||||
{
|
|
||||||
static const rectangle rect(SPEC_LEFT_BORDER, SPEC_LEFT_BORDER + SPEC_DISPLAY_XSIZE - 1, SPEC_TOP_BORDER, SPEC_TOP_BORDER + SPEC_DISPLAY_YSIZE - 1);
|
|
||||||
|
|
||||||
if (m_border_bitmap.valid())
|
|
||||||
copyscrollbitmap(bitmap, m_border_bitmap, 0, nullptr, 0, nullptr, cliprect);
|
|
||||||
|
|
||||||
spectrum_UpdateScreenBitmap();
|
|
||||||
if (m_screen_bitmap.valid())
|
|
||||||
copyscrollbitmap(bitmap, m_screen_bitmap, 0, nullptr, 0, nullptr, rect);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// note, don't update borders in here, this can time travel w/regards to other timers and may end up giving you
|
|
||||||
// screen positions earlier than the last write handler gave you
|
|
||||||
|
|
||||||
/* for now do a full-refresh */
|
|
||||||
int x, y, b, scrx, scry;
|
|
||||||
unsigned short ink, pap;
|
|
||||||
unsigned char *attr, *scr;
|
|
||||||
// int full_refresh = 1;
|
|
||||||
|
|
||||||
scr=m_screen_location;
|
|
||||||
|
|
||||||
for (y=0; y<192; y++)
|
|
||||||
{
|
|
||||||
scrx=SPEC_LEFT_BORDER;
|
|
||||||
scry=((y&7) * 8) + ((y&0x38)>>3) + (y&0xC0);
|
|
||||||
attr=m_screen_location + ((scry>>3)*32) + 0x1800;
|
|
||||||
|
|
||||||
for (x=0;x<32;x++)
|
|
||||||
{
|
|
||||||
/* Get ink and paper colour with bright */
|
|
||||||
if (m_flash_invert && (*attr & 0x80))
|
|
||||||
{
|
|
||||||
ink=((*attr)>>3) & 0x0f;
|
|
||||||
pap=((*attr) & 0x07) + (((*attr)>>3) & 0x08);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ink=((*attr) & 0x07) + (((*attr)>>3) & 0x08);
|
|
||||||
pap=((*attr)>>3) & 0x0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (b=0x80;b!=0;b>>=1)
|
|
||||||
{
|
|
||||||
if (*scr&b)
|
|
||||||
spectrum_plot_pixel(bitmap,scrx++,SPEC_TOP_BORDER+scry,ink);
|
|
||||||
else
|
|
||||||
spectrum_plot_pixel(bitmap,scrx++,SPEC_TOP_BORDER+scry,pap);
|
|
||||||
}
|
|
||||||
|
|
||||||
scr++;
|
|
||||||
attr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static constexpr rgb_t spectrum_pens[16] = {
|
static constexpr rgb_t spectrum_pens[16] = {
|
||||||
{ 0x00, 0x00, 0x00 },
|
{ 0x00, 0x00, 0x00 },
|
||||||
{ 0x00, 0x00, 0xbf },
|
{ 0x00, 0x00, 0xbf },
|
||||||
@ -205,111 +77,83 @@ static constexpr rgb_t spectrum_pens[16] = {
|
|||||||
{ 0xff, 0xff, 0x00 },
|
{ 0xff, 0xff, 0x00 },
|
||||||
{ 0xff, 0xff, 0xff }
|
{ 0xff, 0xff, 0xff }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialise the palette
|
// Initialise the palette
|
||||||
void spectrum_state::spectrum_palette(palette_device &palette) const
|
void spectrum_state::spectrum_palette(palette_device &palette) const
|
||||||
{
|
{
|
||||||
palette.set_pen_colors(0, spectrum_pens);
|
palette.set_pen_colors(0, spectrum_pens);
|
||||||
}
|
}
|
||||||
|
|
||||||
void spectrum_state::spectrum_UpdateScreenBitmap(bool eof)
|
rectangle spectrum_state::get_screen_area()
|
||||||
{
|
{
|
||||||
unsigned int x = m_screen->hpos();
|
// 256x192 screen position without border
|
||||||
unsigned int y = m_screen->vpos();
|
return rectangle{48, 48 + 255, 64, 64 + 191};
|
||||||
int width = m_screen_bitmap.width();
|
|
||||||
int height = m_screen_bitmap.height();
|
|
||||||
|
|
||||||
|
|
||||||
if ((m_previous_screen_x == x) && (m_previous_screen_y == y) && !eof)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_screen_bitmap.valid())
|
|
||||||
{
|
|
||||||
//printf("update screen from %d,%d to %d,%d\n", m_previous_screen_x, m_previous_screen_y, x, y);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
uint16_t scrx = m_previous_screen_x - SPEC_LEFT_BORDER;
|
|
||||||
uint16_t scry = m_previous_screen_y - SPEC_TOP_BORDER;
|
|
||||||
|
|
||||||
if (scrx < SPEC_DISPLAY_XSIZE && scry < SPEC_DISPLAY_YSIZE)
|
|
||||||
{
|
|
||||||
// this can/must be optimised
|
|
||||||
if ((scrx & 7) == 0) {
|
|
||||||
uint16_t *bm = &m_screen_bitmap.pix(m_previous_screen_y, m_previous_screen_x);
|
|
||||||
uint8_t attr = *(m_screen_location + ((scry & 0xF8) << 2) + (scrx >> 3) + 0x1800);
|
|
||||||
uint8_t scr = *(m_screen_location + ((scry & 7) << 8) + ((scry & 0x38) << 2) + ((scry & 0xC0) << 5) + (scrx >> 3));
|
|
||||||
uint16_t ink = (attr & 0x07) + ((attr >> 3) & 0x08);
|
|
||||||
uint16_t pap = (attr >> 3) & 0x0f;
|
|
||||||
|
|
||||||
if (m_flash_invert && (attr & 0x80))
|
|
||||||
scr = ~scr;
|
|
||||||
|
|
||||||
for (uint8_t b = 0x80; b != 0; b >>= 1)
|
|
||||||
*bm++ = (scr & b) ? ink : pap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_previous_screen_x += 1;
|
|
||||||
|
|
||||||
if (m_previous_screen_x >= width)
|
|
||||||
{
|
|
||||||
m_previous_screen_x = 0;
|
|
||||||
m_previous_screen_y += 1;
|
|
||||||
|
|
||||||
if (m_previous_screen_y >= height)
|
|
||||||
{
|
|
||||||
m_previous_screen_y = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!((m_previous_screen_x == x) && (m_previous_screen_y == y)));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 spectrum_state::get_border_color() {
|
u8 spectrum_state::get_border_color(u16 hpos, u16 vpos)
|
||||||
|
{
|
||||||
|
//TODO snow effect
|
||||||
return m_port_fe_data & 0x07;
|
return m_port_fe_data & 0x07;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The code below is just a per-pixel 'partial update' for the border */
|
u32 spectrum_state::screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||||
|
|
||||||
void spectrum_state::spectrum_UpdateBorderBitmap()
|
|
||||||
{
|
{
|
||||||
unsigned int x = m_screen->hpos();
|
rectangle scr = get_screen_area();
|
||||||
unsigned int y = m_screen->vpos();
|
rectangle vis = screen.visible_area();
|
||||||
int width = m_border_bitmap.width();
|
if (vis != scr) {
|
||||||
int height = m_border_bitmap.height();
|
rectangle bsides[4] = {
|
||||||
|
rectangle(vis.left(), vis.right(), vis.top(), scr.top() - 1),
|
||||||
|
rectangle(vis.left(), scr.left() - 1, scr.top(), scr.bottom()),
|
||||||
if (m_border_bitmap.valid())
|
rectangle(scr.right() + 1, vis.right(), scr.top(), scr.bottom()),
|
||||||
|
rectangle(vis.left(), vis.right(), scr.bottom() + 1, vis.bottom())
|
||||||
|
};
|
||||||
|
for (auto i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
uint16_t border = get_border_color();
|
rectangle border = bsides[i] & cliprect;
|
||||||
|
if (!border.empty())
|
||||||
//printf("update border from %d,%d to %d,%d\n", m_previous_border_x, m_previous_border_y, x, y);
|
spectrum_update_border(screen, bitmap, border);
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
m_border_bitmap.pix(m_previous_border_y, m_previous_border_x) = border;
|
|
||||||
|
|
||||||
m_previous_border_x += 1;
|
|
||||||
|
|
||||||
if (m_previous_border_x >= width)
|
|
||||||
{
|
|
||||||
m_previous_border_x = 0;
|
|
||||||
m_previous_border_y += 1;
|
|
||||||
|
|
||||||
if (m_previous_border_y >= height)
|
|
||||||
{
|
|
||||||
m_previous_border_y = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
while (!((m_previous_border_x == x) && (m_previous_border_y == y)));
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// no border bitmap allocated? fatalerror?
|
|
||||||
}
|
|
||||||
|
|
||||||
|
scr &= cliprect;
|
||||||
|
if (!scr.empty())
|
||||||
|
spectrum_update_screen(screen, bitmap, scr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spectrum_state::spectrum_update_border(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &border)
|
||||||
|
{
|
||||||
|
for (auto y = border.top(); y <= border.bottom(); y++)
|
||||||
|
{
|
||||||
|
u16 *pix = &(bitmap.pix(y, border.left()));
|
||||||
|
for (auto x = border.left(); x <= border.right(); x++)
|
||||||
|
*pix++ = get_border_color(y, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void spectrum_state::spectrum_update_screen(screen_device &screen_d, bitmap_ind16 &bitmap, const rectangle &screen)
|
||||||
|
{
|
||||||
|
u8 *attrs_location = m_screen_location + 0x1800;
|
||||||
|
bool invert_attrs = u64(screen_d.frame_number() / m_frame_invert_count) & 1;
|
||||||
|
for (u16 vpos = screen.top(); vpos <= screen.bottom(); vpos++)
|
||||||
|
{
|
||||||
|
u16 hpos = screen.left();
|
||||||
|
u16 x = hpos - get_screen_area().left();
|
||||||
|
u16 y = vpos - get_screen_area().top();
|
||||||
|
u8 *scr = &m_screen_location[((y & 7) << 8) | ((y & 0x38) << 2) | ((y & 0xc0) << 5) | (x >> 3)];
|
||||||
|
u8 *attr = &attrs_location[((y & 0xf8) << 2) | (x >> 3)];
|
||||||
|
u16 *pix = &(bitmap.pix(vpos, hpos));
|
||||||
|
while (hpos <= screen.right())
|
||||||
|
{
|
||||||
|
u16 ink = ((*attr >> 3) & 0x08) | (*attr & 0x07);
|
||||||
|
u16 pap = (*attr >> 3) & 0x0f;
|
||||||
|
u8 pix8 = (invert_attrs && (*attr & 0x80)) ? ~*scr : *scr;
|
||||||
|
|
||||||
|
for (u8 b = 0x80 >> (x & 0x07); b != 0 && hpos <= screen.right(); b >>= 1, x++, hpos++)
|
||||||
|
*pix++ = (pix8 & b) ? ink : pap;
|
||||||
|
scr++;
|
||||||
|
attr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,44 +22,15 @@
|
|||||||
|
|
||||||
inline void tc2048_state::spectrum_plot_pixel(bitmap_ind16 &bitmap, int x, int y, uint32_t color)
|
inline void tc2048_state::spectrum_plot_pixel(bitmap_ind16 &bitmap, int x, int y, uint32_t color)
|
||||||
{
|
{
|
||||||
bitmap.pix(y, x) = (uint16_t)color;
|
rectangle screen = m_screen->visible_area();
|
||||||
|
bitmap.pix(screen.top() + y, screen.left() + x) = (uint16_t)color;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update FLASH status for ts2068. Assumes flash update every 1/2s. */
|
/* Update FLASH status for ts2068. Assumes flash update every 1/2s. */
|
||||||
void ts2068_state::video_start()
|
void ts2068_state::video_start()
|
||||||
{
|
{
|
||||||
m_frame_invert_count = 30;
|
m_frame_invert_count = 30;
|
||||||
|
|
||||||
m_frame_number = 0;
|
|
||||||
m_flash_invert = 0;
|
|
||||||
|
|
||||||
m_previous_border_x = 0;
|
|
||||||
m_previous_border_y = 0;
|
|
||||||
m_screen->register_screen_bitmap(m_border_bitmap);
|
|
||||||
m_previous_screen_x = 0;
|
|
||||||
m_previous_screen_y = 0;
|
|
||||||
m_screen->register_screen_bitmap(m_screen_bitmap);
|
|
||||||
|
|
||||||
m_screen_location = m_video_ram;
|
m_screen_location = m_video_ram;
|
||||||
|
|
||||||
m_irq_off_timer = timer_alloc(TIMER_IRQ_OFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
WRITE_LINE_MEMBER(tc2048_state::screen_vblank_timex)
|
|
||||||
{
|
|
||||||
// rising edge
|
|
||||||
if (state)
|
|
||||||
{
|
|
||||||
spectrum_UpdateBorderBitmap();
|
|
||||||
|
|
||||||
m_frame_number++;
|
|
||||||
|
|
||||||
if (m_frame_number >= m_frame_invert_count)
|
|
||||||
{
|
|
||||||
m_frame_number = 0;
|
|
||||||
m_flash_invert = !m_flash_invert;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -91,6 +62,7 @@ void tc2048_state::hires_scanline(bitmap_ind16 &bitmap, int y, int borderlines)
|
|||||||
int x,b,scrx,scry;
|
int x,b,scrx,scry;
|
||||||
unsigned short ink,pap;
|
unsigned short ink,pap;
|
||||||
unsigned char *attr, *scr;
|
unsigned char *attr, *scr;
|
||||||
|
bool invert_attrs = u64(m_screen->frame_number() / m_frame_invert_count) & 1;
|
||||||
|
|
||||||
scrx=TS2068_LEFT_BORDER;
|
scrx=TS2068_LEFT_BORDER;
|
||||||
scry=((y&7) * 8) + ((y&0x38)>>3) + (y&0xC0);
|
scry=((y&7) * 8) + ((y&0x38)>>3) + (y&0xC0);
|
||||||
@ -101,7 +73,7 @@ void tc2048_state::hires_scanline(bitmap_ind16 &bitmap, int y, int borderlines)
|
|||||||
for (x=0;x<32;x++)
|
for (x=0;x<32;x++)
|
||||||
{
|
{
|
||||||
/* Get ink and paper colour with bright */
|
/* Get ink and paper colour with bright */
|
||||||
if (m_flash_invert && (*attr & 0x80))
|
if (invert_attrs && (*attr & 0x80))
|
||||||
{
|
{
|
||||||
ink=((*attr)>>3) & 0x0f;
|
ink=((*attr)>>3) & 0x0f;
|
||||||
pap=((*attr) & 0x07) + (((*attr)>>3) & 0x08);
|
pap=((*attr) & 0x07) + (((*attr)>>3) & 0x08);
|
||||||
@ -116,13 +88,13 @@ void tc2048_state::hires_scanline(bitmap_ind16 &bitmap, int y, int borderlines)
|
|||||||
{
|
{
|
||||||
if (*scr&b)
|
if (*scr&b)
|
||||||
{
|
{
|
||||||
spectrum_plot_pixel(bitmap,scrx++,scry+borderlines,ink);
|
spectrum_plot_pixel(bitmap, scrx++,scry+borderlines,ink);
|
||||||
spectrum_plot_pixel(bitmap,scrx++,scry+borderlines,ink);
|
spectrum_plot_pixel(bitmap, scrx++,scry+borderlines,ink);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
spectrum_plot_pixel(bitmap,scrx++,scry+borderlines,pap);
|
spectrum_plot_pixel(bitmap, scrx++,scry+borderlines,pap);
|
||||||
spectrum_plot_pixel(bitmap,scrx++,scry+borderlines,pap);
|
spectrum_plot_pixel(bitmap, scrx++,scry+borderlines,pap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scr++;
|
scr++;
|
||||||
@ -147,18 +119,18 @@ void tc2048_state::_64col_scanline(bitmap_ind16 &bitmap, int y, int borderlines,
|
|||||||
for (b=0x80;b!=0;b>>=1)
|
for (b=0x80;b!=0;b>>=1)
|
||||||
{
|
{
|
||||||
if (*scr1&b)
|
if (*scr1&b)
|
||||||
spectrum_plot_pixel(bitmap,scrx++,scry+borderlines,inkcolor);
|
spectrum_plot_pixel(bitmap, scrx++,scry+borderlines,inkcolor);
|
||||||
else
|
else
|
||||||
spectrum_plot_pixel(bitmap,scrx++,scry+borderlines,7-inkcolor);
|
spectrum_plot_pixel(bitmap, scrx++,scry+borderlines,7-inkcolor);
|
||||||
}
|
}
|
||||||
scr1++;
|
scr1++;
|
||||||
|
|
||||||
for (b=0x80;b!=0;b>>=1)
|
for (b=0x80;b!=0;b>>=1)
|
||||||
{
|
{
|
||||||
if (*scr2&b)
|
if (*scr2&b)
|
||||||
spectrum_plot_pixel(bitmap,scrx++,scry+borderlines,inkcolor);
|
spectrum_plot_pixel(bitmap, scrx++,scry+borderlines,inkcolor);
|
||||||
else
|
else
|
||||||
spectrum_plot_pixel(bitmap,scrx++,scry+borderlines,7-inkcolor);
|
spectrum_plot_pixel(bitmap, scrx++,scry+borderlines,7-inkcolor);
|
||||||
}
|
}
|
||||||
scr2++;
|
scr2++;
|
||||||
}
|
}
|
||||||
@ -170,6 +142,7 @@ void tc2048_state::lores_scanline(bitmap_ind16 &bitmap, int y, int borderlines,
|
|||||||
int x,b,scrx,scry;
|
int x,b,scrx,scry;
|
||||||
unsigned short ink,pap;
|
unsigned short ink,pap;
|
||||||
unsigned char *attr, *scr;
|
unsigned char *attr, *scr;
|
||||||
|
bool invert_attrs = u64(m_screen->frame_number() / m_frame_invert_count) & 1;
|
||||||
|
|
||||||
scrx=TS2068_LEFT_BORDER;
|
scrx=TS2068_LEFT_BORDER;
|
||||||
scry=((y&7) * 8) + ((y&0x38)>>3) + (y&0xC0);
|
scry=((y&7) * 8) + ((y&0x38)>>3) + (y&0xC0);
|
||||||
@ -180,7 +153,7 @@ void tc2048_state::lores_scanline(bitmap_ind16 &bitmap, int y, int borderlines,
|
|||||||
for (x=0;x<32;x++)
|
for (x=0;x<32;x++)
|
||||||
{
|
{
|
||||||
/* Get ink and paper colour with bright */
|
/* Get ink and paper colour with bright */
|
||||||
if (m_flash_invert && (*attr & 0x80))
|
if (invert_attrs && (*attr & 0x80))
|
||||||
{
|
{
|
||||||
ink=((*attr)>>3) & 0x0f;
|
ink=((*attr)>>3) & 0x0f;
|
||||||
pap=((*attr) & 0x07) + (((*attr)>>3) & 0x08);
|
pap=((*attr) & 0x07) + (((*attr)>>3) & 0x08);
|
||||||
@ -195,13 +168,13 @@ void tc2048_state::lores_scanline(bitmap_ind16 &bitmap, int y, int borderlines,
|
|||||||
{
|
{
|
||||||
if (*scr&b)
|
if (*scr&b)
|
||||||
{
|
{
|
||||||
spectrum_plot_pixel(bitmap,scrx++,scry+borderlines,ink);
|
spectrum_plot_pixel(bitmap, scrx++,scry+borderlines,ink);
|
||||||
spectrum_plot_pixel(bitmap,scrx++,scry+borderlines,ink);
|
spectrum_plot_pixel(bitmap, scrx++,scry+borderlines,ink);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
spectrum_plot_pixel(bitmap,scrx++,scry+borderlines,pap);
|
spectrum_plot_pixel(bitmap, scrx++,scry+borderlines,pap);
|
||||||
spectrum_plot_pixel(bitmap,scrx++,scry+borderlines,pap);
|
spectrum_plot_pixel(bitmap, scrx++,scry+borderlines,pap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scr++;
|
scr++;
|
||||||
@ -209,76 +182,35 @@ void tc2048_state::lores_scanline(bitmap_ind16 &bitmap, int y, int borderlines,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ts2068_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
void tc2048_state::spectrum_update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||||
{
|
{
|
||||||
/* for now TS2068 will do a full-refresh */
|
/* for now TC2048/TS2068 will do a full-refresh */
|
||||||
int count;
|
if (cliprect.bottom() != get_screen_area().bottom() || cliprect.right() != get_screen_area().right())
|
||||||
|
return;
|
||||||
if (m_border_bitmap.valid())
|
|
||||||
copyscrollbitmap(bitmap, m_border_bitmap, 0, nullptr, 0, nullptr, cliprect);
|
|
||||||
|
|
||||||
if ((m_port_ff_data & 7) == 6)
|
if ((m_port_ff_data & 7) == 6)
|
||||||
{
|
{
|
||||||
/* 64 Column mode */
|
/* 64 Column mode */
|
||||||
unsigned short inkcolor = (m_port_ff_data & 0x38) >> 3;
|
unsigned short inkcolor = (m_port_ff_data & 0x38) >> 3;
|
||||||
for (count = 0; count < 192; count++)
|
for (auto count = 0; count < 192; count++)
|
||||||
_64col_scanline(bitmap, count, TS2068_TOP_BORDER, inkcolor);
|
_64col_scanline(bitmap, count, TS2068_TOP_BORDER, inkcolor);
|
||||||
}
|
}
|
||||||
else if ((m_port_ff_data & 7) == 2)
|
else if ((m_port_ff_data & 7) == 2)
|
||||||
{
|
{
|
||||||
/* Extended Color mode */
|
/* Extended Color mode */
|
||||||
for (count = 0; count < 192; count++)
|
for (auto count = 0; count < 192; count++)
|
||||||
hires_scanline(bitmap, count, TS2068_TOP_BORDER);
|
hires_scanline(bitmap, count, TS2068_TOP_BORDER);
|
||||||
}
|
}
|
||||||
else if ((m_port_ff_data & 7) == 1)
|
else if ((m_port_ff_data & 7) == 1)
|
||||||
{
|
{
|
||||||
/* Screen 6000-7aff */
|
/* Screen 6000-7aff */
|
||||||
for (count = 0; count < 192; count++)
|
for (auto count = 0; count < 192; count++)
|
||||||
lores_scanline(bitmap, count, TS2068_TOP_BORDER, 1);
|
lores_scanline(bitmap, count, TS2068_TOP_BORDER, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Screen 4000-5aff */
|
/* Screen 4000-5aff */
|
||||||
for (count = 0; count < 192; count++)
|
for (auto count = 0; count < 192; count++)
|
||||||
lores_scanline(bitmap, count, TS2068_TOP_BORDER, 0);
|
lores_scanline(bitmap, count, TS2068_TOP_BORDER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t tc2048_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
|
||||||
{
|
|
||||||
/* for now TC2048 will do a full-refresh */
|
|
||||||
int count;
|
|
||||||
|
|
||||||
if (m_border_bitmap.valid())
|
|
||||||
copyscrollbitmap(bitmap, m_border_bitmap, 0, nullptr, 0, nullptr, cliprect);
|
|
||||||
|
|
||||||
if ((m_port_ff_data & 7) == 6)
|
|
||||||
{
|
|
||||||
/* 64 Column mode */
|
|
||||||
unsigned short inkcolor = (m_port_ff_data & 0x38) >> 3;
|
|
||||||
for (count = 0; count < 192; count++)
|
|
||||||
_64col_scanline(bitmap, count, SPEC_TOP_BORDER, inkcolor);
|
|
||||||
}
|
|
||||||
else if ((m_port_ff_data & 7) == 2)
|
|
||||||
{
|
|
||||||
/* Extended Color mode */
|
|
||||||
for (count = 0; count < 192; count++)
|
|
||||||
hires_scanline(bitmap, count, SPEC_TOP_BORDER);
|
|
||||||
}
|
|
||||||
else if ((m_port_ff_data & 7) == 1)
|
|
||||||
{
|
|
||||||
/* Screen 6000-7aff */
|
|
||||||
for (count = 0; count < 192; count++)
|
|
||||||
lores_scanline(bitmap, count, SPEC_TOP_BORDER, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Screen 4000-5aff */
|
|
||||||
for (count = 0; count < 192; count++)
|
|
||||||
lores_scanline(bitmap, count, SPEC_TOP_BORDER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user