mirror of
https://github.com/holub/mame
synced 2025-10-05 08:41:31 +03:00
abc80: Converted to scanline based rendering, partially fixing hiresinv demo. [Curt Coder]
This commit is contained in:
parent
29a3f8b488
commit
93f8b62a16
@ -65,6 +65,7 @@ Notes:
|
||||
|
||||
TODO:
|
||||
|
||||
- hiresinv graphics artifacts
|
||||
- proper keyboard controller emulation
|
||||
- MyAB TKN80 80-column card
|
||||
- GeJo 80-column card
|
||||
@ -393,12 +394,6 @@ WRITE8_MEMBER( abc80_state::kbd_w )
|
||||
timer_set(attotime::from_msec(50), TIMER_ID_FAKE_KEYBOARD_CLEAR);
|
||||
}
|
||||
|
||||
/*
|
||||
DEVICE_INPUT_DEFAULTS_START( abc830_slow )
|
||||
DEVICE_INPUT_DEFAULTS("SW1", 0x0f, 0x03)
|
||||
DEVICE_INPUT_DEFAULTS("S1", 0x01, 0x01)
|
||||
DEVICE_INPUT_DEFAULTS_END
|
||||
*/
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
@ -413,7 +408,9 @@ void abc80_state::device_timer(emu_timer &timer, device_timer_id id, int param,
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case TIMER_ID_PIO:
|
||||
case TIMER_ID_SCANLINE:
|
||||
draw_scanline(m_bitmap, m_screen->vpos());
|
||||
|
||||
m_pio_astb = !m_pio_astb;
|
||||
|
||||
m_pio->strobe_a(m_pio_astb);
|
||||
@ -628,4 +625,4 @@ ROM_END
|
||||
//**************************************************************************
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1978, abc80, 0, 0, abc80, abc80, driver_device, 0, "Luxor Datorer AB", "ABC 80", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_KEYBOARD )
|
||||
COMP( 1978, abc80, 0, 0, abc80, abc80, driver_device, 0, "Luxor Datorer AB", "ABC 80", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_KEYBOARD )
|
||||
|
@ -27,9 +27,9 @@
|
||||
#define ABC80_HTOTAL 384
|
||||
#define ABC80_HBEND 35
|
||||
#define ABC80_HBSTART 384
|
||||
#define ABC80_VTOTAL 312
|
||||
#define ABC80_VTOTAL 313
|
||||
#define ABC80_VBEND 15
|
||||
#define ABC80_VBSTART 312
|
||||
#define ABC80_VBSTART 313
|
||||
|
||||
#define ABC80_K5_HSYNC 0x01
|
||||
#define ABC80_K5_DH 0x02
|
||||
@ -76,6 +76,7 @@ public:
|
||||
m_ram(*this, RAM_TAG),
|
||||
m_rs232(*this, RS232_TAG),
|
||||
m_palette(*this, "palette"),
|
||||
m_screen(*this, SCREEN_TAG),
|
||||
m_rom(*this, Z80_TAG),
|
||||
m_mmu_rom(*this, "mmu"),
|
||||
m_char_rom(*this, "chargen"),
|
||||
@ -98,6 +99,7 @@ public:
|
||||
required_device<ram_device> m_ram;
|
||||
required_device<rs232_port_device> m_rs232;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<screen_device> m_screen;
|
||||
required_memory_region m_rom;
|
||||
required_memory_region m_mmu_rom;
|
||||
required_memory_region m_char_rom;
|
||||
@ -109,7 +111,7 @@ public:
|
||||
|
||||
enum
|
||||
{
|
||||
TIMER_ID_PIO,
|
||||
TIMER_ID_SCANLINE,
|
||||
TIMER_ID_CASSETTE,
|
||||
TIMER_ID_BLINK,
|
||||
TIMER_ID_VSYNC_ON,
|
||||
@ -131,7 +133,7 @@ public:
|
||||
virtual void video_start() override;
|
||||
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
void update_screen(bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
void draw_scanline(bitmap_rgb32 &bitmap, int y);
|
||||
|
||||
DECLARE_READ8_MEMBER( read );
|
||||
DECLARE_WRITE8_MEMBER( write );
|
||||
@ -161,8 +163,12 @@ public:
|
||||
int m_pio_astb;
|
||||
|
||||
// video state
|
||||
bitmap_rgb32 m_bitmap;
|
||||
uint8_t m_latch;
|
||||
int m_blink;
|
||||
int m_c;
|
||||
int m_r;
|
||||
int m_mode;
|
||||
|
||||
// cassette state
|
||||
bool m_motor;
|
||||
@ -170,7 +176,7 @@ public:
|
||||
int m_tape_in_latch;
|
||||
|
||||
// timers
|
||||
emu_timer *m_pio_timer;
|
||||
emu_timer *m_scanline_timer;
|
||||
emu_timer *m_cassette_timer;
|
||||
emu_timer *m_blink_timer;
|
||||
emu_timer *m_vsync_on_timer;
|
||||
|
@ -37,154 +37,152 @@ static GFXDECODE_START( abc80 )
|
||||
GFXDECODE_END
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// update_screen -
|
||||
//-------------------------------------------------
|
||||
|
||||
void abc80_state::update_screen(bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
void abc80_state::draw_scanline(bitmap_rgb32 &bitmap, int y)
|
||||
{
|
||||
int c = 0;
|
||||
int r = 0;
|
||||
int mode = 0;
|
||||
uint8_t vsync_data = m_vsync_prom->base()[y];
|
||||
uint8_t l = m_line_prom->base()[y];
|
||||
int dv = (vsync_data & ABC80_K2_DV) ? 1 : 0;
|
||||
|
||||
for (int y = 0; y < 312; y++)
|
||||
if (!(vsync_data & ABC80_K2_FRAME_RESET))
|
||||
{
|
||||
uint8_t vsync_data = m_vsync_prom->base()[y];
|
||||
uint8_t l = m_line_prom->base()[y];
|
||||
int dv = (vsync_data & ABC80_K2_DV) ? 1 : 0;
|
||||
// reset F2
|
||||
m_r = 0;
|
||||
}
|
||||
|
||||
if (!(vsync_data & ABC80_K2_FRAME_RESET))
|
||||
for (int sx = 0; sx < 64; sx++)
|
||||
{
|
||||
uint8_t hsync_data = m_hsync_prom->base()[sx];
|
||||
if (!y) logerror("y %u sx %u HSYNC %u HV %u RE %u RR %u\n",y,sx,BIT(hsync_data,0),BIT(hsync_data,1),BIT(hsync_data,2),BIT(hsync_data,3));
|
||||
int dh = (hsync_data & ABC80_K5_DH) ? 1 : 0;
|
||||
uint8_t data = 0;
|
||||
|
||||
if (hsync_data & ABC80_K5_LINE_END)
|
||||
{
|
||||
// reset F2
|
||||
r = 0;
|
||||
// reset F4
|
||||
m_c = 0;
|
||||
|
||||
// reset J5
|
||||
m_mode = 0;
|
||||
}
|
||||
|
||||
for (int sx = 0; sx < 64; sx++)
|
||||
/*
|
||||
|
||||
Video RAM Addressing Scheme
|
||||
|
||||
A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
|
||||
R2 R1 R0 xx xx xx xx C2 C1 C0
|
||||
|
||||
A6 A5 A4 A3 = 00 C5 C4 C3 + R4 R3 R4 R3
|
||||
|
||||
*/
|
||||
|
||||
int a = (m_c >> 3) & 0x07;
|
||||
int b = ((m_r >> 1) & 0x0c) | ((m_r >> 3) & 0x03);
|
||||
int s = (a + b) & 0x0f;
|
||||
uint16_t videoram_addr = ((m_r & 0x07) << 7) | (s << 3) | (m_c & 0x07);
|
||||
uint8_t videoram_data = m_latch;
|
||||
uint8_t attr_addr = ((dh & dv) << 7) | (videoram_data & 0x7f);
|
||||
uint8_t attr_data = m_attr_prom->base()[attr_addr];
|
||||
|
||||
int blank = (attr_data & ABC80_J3_BLANK) ? 1 : 0;
|
||||
int j = (attr_data & ABC80_J3_TEXT) ? 1 : 0;
|
||||
int k = (attr_data & ABC80_J3_GRAPHICS) ? 1 : 0;
|
||||
int versal = (attr_data & ABC80_J3_VERSAL) ? 1 : 0;
|
||||
int cursor = (videoram_data & ABC80_CHAR_CURSOR) ? 1 : 0;
|
||||
|
||||
if (!j && k) m_mode = 0;
|
||||
if (j && !k) m_mode = 1;
|
||||
if (j && k) m_mode = !m_mode;
|
||||
|
||||
if (m_mode & versal)
|
||||
{
|
||||
uint8_t hsync_data = m_hsync_prom->base()[sx];
|
||||
int dh = (hsync_data & ABC80_K5_DH) ? 1 : 0;
|
||||
uint8_t data = 0;
|
||||
// graphics mode
|
||||
int r0 = 1, r1 = 1, r2 = 1;
|
||||
|
||||
if (hsync_data & ABC80_K5_LINE_END)
|
||||
{
|
||||
// reset F4
|
||||
c = 0;
|
||||
if (l < 3) r0 = 0; else if (l < 7) r1 = 0; else r2 = 0;
|
||||
|
||||
// reset J5
|
||||
mode = 0;
|
||||
}
|
||||
int c0 = BIT(videoram_data, 0) | r0;
|
||||
int c1 = BIT(videoram_data, 1) | r0;
|
||||
int c2 = BIT(videoram_data, 2) | r1;
|
||||
int c3 = BIT(videoram_data, 3) | r1;
|
||||
int c4 = BIT(videoram_data, 4) | r2;
|
||||
int c5 = BIT(videoram_data, 6) | r2;
|
||||
|
||||
/*
|
||||
if (!(c0 & c2 & c4)) data |= 0xe0;
|
||||
if (!(c1 & c3 & c5)) data |= 0x1c;
|
||||
}
|
||||
else
|
||||
{
|
||||
// text mode
|
||||
uint16_t chargen_addr = ((videoram_data & 0x7f) * 10) + l;
|
||||
|
||||
Video RAM Addressing Scheme
|
||||
|
||||
A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
|
||||
R2 R1 R0 xx xx xx xx C2 C1 C0
|
||||
|
||||
A6 A5 A4 A3 = 00 C5 C4 C3 + R4 R3 R4 R3
|
||||
|
||||
*/
|
||||
|
||||
int a = (c >> 3) & 0x07;
|
||||
int b = ((r >> 1) & 0x0c) | ((r >> 3) & 0x03);
|
||||
int s = (a + b) & 0x0f;
|
||||
uint16_t videoram_addr = ((r & 0x07) << 7) | (s << 3) | (c & 0x07);
|
||||
uint8_t videoram_data = m_latch;
|
||||
uint8_t attr_addr = ((dh & dv) << 7) | (videoram_data & 0x7f);
|
||||
uint8_t attr_data = m_attr_prom->base()[attr_addr];
|
||||
|
||||
int blank = (attr_data & ABC80_J3_BLANK) ? 1 : 0;
|
||||
int j = (attr_data & ABC80_J3_TEXT) ? 1 : 0;
|
||||
int k = (attr_data & ABC80_J3_GRAPHICS) ? 1 : 0;
|
||||
int versal = (attr_data & ABC80_J3_VERSAL) ? 1 : 0;
|
||||
int cursor = (videoram_data & ABC80_CHAR_CURSOR) ? 1 : 0;
|
||||
|
||||
if (!j && k) mode = 0;
|
||||
if (j && !k) mode = 1;
|
||||
if (j && k) mode = !mode;
|
||||
|
||||
if (mode & versal)
|
||||
{
|
||||
// graphics mode
|
||||
int r0 = 1, r1 = 1, r2 = 1;
|
||||
|
||||
if (l < 3) r0 = 0; else if (l < 7) r1 = 0; else r2 = 0;
|
||||
|
||||
int c0 = BIT(videoram_data, 0) | r0;
|
||||
int c1 = BIT(videoram_data, 1) | r0;
|
||||
int c2 = BIT(videoram_data, 2) | r1;
|
||||
int c3 = BIT(videoram_data, 3) | r1;
|
||||
int c4 = BIT(videoram_data, 4) | r2;
|
||||
int c5 = BIT(videoram_data, 6) | r2;
|
||||
|
||||
if (!(c0 & c2 & c4)) data |= 0xe0;
|
||||
if (!(c1 & c3 & c5)) data |= 0x1c;
|
||||
}
|
||||
else
|
||||
{
|
||||
// text mode
|
||||
uint16_t chargen_addr = ((videoram_data & 0x7f) * 10) + l;
|
||||
|
||||
data = m_char_rom->base()[chargen_addr];
|
||||
}
|
||||
|
||||
// shift out pixels
|
||||
for (int bit = 0; bit < 6; bit++)
|
||||
{
|
||||
int color = BIT(data, 7);
|
||||
int x = (sx * 6) + bit;
|
||||
|
||||
color ^= (cursor & m_blink);
|
||||
color &= blank;
|
||||
|
||||
bitmap.pix32(y, x) = m_palette->pen(color);
|
||||
|
||||
data <<= 1;
|
||||
}
|
||||
|
||||
m_latch = m_video_ram[videoram_addr];
|
||||
|
||||
if (hsync_data & ABC80_K5_ROW_START)
|
||||
{
|
||||
// clock F4
|
||||
c++;
|
||||
}
|
||||
data = m_char_rom->base()[chargen_addr];
|
||||
}
|
||||
|
||||
if (vsync_data & ABC80_K2_FRAME_END)
|
||||
// shift out pixels
|
||||
for (int bit = 0; bit < 6; bit++)
|
||||
{
|
||||
// clock F2
|
||||
r++;
|
||||
int color = BIT(data, 7);
|
||||
int x = (sx * 6) + bit;
|
||||
|
||||
color ^= (cursor & m_blink);
|
||||
color &= blank;
|
||||
|
||||
bitmap.pix32(y, x) = m_palette->pen(color);
|
||||
|
||||
data <<= 1;
|
||||
}
|
||||
|
||||
m_latch = m_video_ram[videoram_addr];
|
||||
|
||||
if (hsync_data & ABC80_K5_ROW_START)
|
||||
{
|
||||
// clock F4
|
||||
m_c++;
|
||||
}
|
||||
}
|
||||
|
||||
if (vsync_data & ABC80_K2_FRAME_END)
|
||||
{
|
||||
// clock F2
|
||||
m_r++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// video_start -
|
||||
//-------------------------------------------------
|
||||
|
||||
void abc80_state::video_start()
|
||||
{
|
||||
screen_device *screen = machine().device<screen_device>(SCREEN_TAG);
|
||||
|
||||
m_screen->register_screen_bitmap(m_bitmap);
|
||||
|
||||
// start timers
|
||||
m_pio_timer = timer_alloc(TIMER_ID_PIO);
|
||||
m_pio_timer->adjust(screen->time_until_pos(0, 0), 0, screen->scan_period());
|
||||
m_scanline_timer = timer_alloc(TIMER_ID_SCANLINE);
|
||||
m_scanline_timer->adjust(m_screen->time_until_pos(0, 0), 0, m_screen->scan_period());
|
||||
|
||||
m_blink_timer = timer_alloc(TIMER_ID_BLINK);
|
||||
m_blink_timer->adjust(attotime::from_hz(XTAL_11_9808MHz/2/6/64/312/16), 0, attotime::from_hz(XTAL_11_9808MHz/2/6/64/312/16));
|
||||
|
||||
m_vsync_on_timer = timer_alloc(TIMER_ID_VSYNC_ON);
|
||||
m_vsync_on_timer->adjust(screen->time_until_pos(0, 0), 0, screen->frame_period());
|
||||
m_vsync_on_timer->adjust(m_screen->time_until_pos(0, 0), 0, m_screen->frame_period());
|
||||
|
||||
m_vsync_off_timer = timer_alloc(TIMER_ID_VSYNC_OFF);
|
||||
m_vsync_off_timer->adjust(screen->time_until_pos(16, 0), 0, screen->frame_period());
|
||||
m_vsync_off_timer->adjust(m_screen->time_until_pos(16, 0), 0, m_screen->frame_period());
|
||||
|
||||
// allocate memory
|
||||
m_video_ram.allocate(0x400);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// screen_update -
|
||||
//-------------------------------------------------
|
||||
|
||||
uint32_t abc80_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
update_screen(bitmap, cliprect);
|
||||
copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user