From e9871210e41619a38480d05caff6a6386533c2a4 Mon Sep 17 00:00:00 2001 From: hap Date: Mon, 3 Aug 2020 20:00:14 +0200 Subject: [PATCH] i8244: fix problem with missing characters, add dot grid --- hash/odyssey2.xml | 8 +-- src/devices/video/i8244.cpp | 116 +++++++++++++++++++++------------- src/mame/drivers/odyssey2.cpp | 89 ++++---------------------- 3 files changed, 87 insertions(+), 126 deletions(-) diff --git a/hash/odyssey2.xml b/hash/odyssey2.xml index 080a1fe7469..0bf3a8c6ab8 100644 --- a/hash/odyssey2.xml +++ b/hash/odyssey2.xml @@ -543,7 +543,7 @@ The C7010 Chess Module had a NSC800 CMOS microprocessor, with 2K RAM and 8K ROM. - + Chess Module (Euro) 1982 Philips @@ -710,7 +710,7 @@ The C7010 Chess Module had a NSC800 CMOS microprocessor, with 2K RAM and 8K ROM. - + Depth Charge/Marksman (Euro) 1980 Philips @@ -1707,7 +1707,7 @@ The C7010 Chess Module had a NSC800 CMOS microprocessor, with 2K RAM and 8K ROM. - + Turtles (Euro) 1982 Philips @@ -1721,7 +1721,7 @@ The C7010 Chess Module had a NSC800 CMOS microprocessor, with 2K RAM and 8K ROM. - + Turtles (USA) 1983 Philips diff --git a/src/devices/video/i8244.cpp b/src/devices/video/i8244.cpp index 3187c987055..e315ceb99be 100644 --- a/src/devices/video/i8244.cpp +++ b/src/devices/video/i8244.cpp @@ -365,27 +365,26 @@ void i8244_device::render_scanline(int vpos) //static const uint8_t COLLISION_EXTERNAL_UNUSED = 0x40; static const uint8_t COLLISION_CHARACTERS = 0x80; - uint8_t collision_map[160]; - if ( vpos == m_start_vpos ) { m_control_status &= ~0x08; } + /* Clear collision map */ + uint8_t collision_map[160]; + memset( collision_map, 0, sizeof( collision_map ) ); + + /* Draw background color */ + rectangle rect(START_ACTIVE_SCAN, END_ACTIVE_SCAN - 1, vpos, vpos); + rect &= screen().visible_area(); + m_tmp_bitmap.fill( (m_vdc.s.color >> 3) & 0x7, rect ); + if ( m_start_vpos < vpos && vpos < m_start_vblank ) { - rectangle rect; int scanline = vpos - m_start_vpos; m_control_status &= ~ 0x01; - /* Draw a line */ - rect.set(START_ACTIVE_SCAN, END_ACTIVE_SCAN - 1, vpos, vpos); - m_tmp_bitmap.fill( (m_vdc.s.color >> 3) & 0x7, rect ); - - /* Clear collision map */ - memset( collision_map, 0, sizeof( collision_map ) ); - /* Display grid if enabled */ if ( m_vdc.s.control & 0x08 ) { @@ -455,18 +454,54 @@ void i8244_device::render_scanline(int vpos) } } } + + /* Draw dots part of the grid */ + if ( m_vdc.s.control & 0x40 ) + { + for ( int y = 0; y < 9; y++ ) + { + if ( y_grid_offset + y * height <= scanline && scanline < y_grid_offset + y * height + 3 ) + { + for ( int i = 0; i < 10; i++ ) + { + for ( int k = 0; k < 2; k++ ) + { + int px = x_grid_offset + i * width + k; + + if ( px < 160 ) + { + /* Check if we collide with an already drawn source object */ + if ( collision_map[ px ] & m_vdc.s.collision ) + { + m_collision_status |= COLLISION_HORIZ_GRID_DOTS; + } + /* Check if an already drawn object would collide with us */ + if ( COLLISION_HORIZ_GRID_DOTS & m_vdc.s.collision && collision_map[ px ] ) + { + m_collision_status |= collision_map[ px ]; + } + collision_map[ px ] |= COLLISION_HORIZ_GRID_DOTS; + m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * px ) = color; + m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * px + 1 ) = color; + } + } + } + } + } + } } /* Display objects if enabled */ if ( m_vdc.s.control & 0x20 ) { /* Regular foreground objects */ - for ( int i = 0; i < ARRAY_LENGTH( m_vdc.s.foreground ); i++ ) + for ( int i = ARRAY_LENGTH( m_vdc.s.foreground ) - 1; i >= 0; i-- ) { int y = m_vdc.s.foreground[i].y & 0xFE; - int height = 8 - ( ( ( y >> 1 ) + m_vdc.s.foreground[i].ptr ) & 7 ); + int height = 8 - ( ( ( y >> 1 ) + m_vdc.s.foreground[i].ptr + 1 ) & 7 ); + if (height == 1) height = 8; - if ( y >= 0x0E && y <= scanline && scanline < y + height * 2 ) + if ( y <= scanline && scanline < y + height * 2 ) { uint16_t color = 8 + bgr2rgb[ ( ( m_vdc.s.foreground[i].color >> 1 ) & 0x07 ) ]; int offset = ( m_vdc.s.foreground[i].ptr | ( ( m_vdc.s.foreground[i].color & 0x01 ) << 8 ) ) + ( y >> 1 ) + ( ( scanline - y ) >> 1 ); @@ -499,59 +534,52 @@ void i8244_device::render_scanline(int vpos) } /* Quad objects */ - for ( int i = 0; i < ARRAY_LENGTH( m_vdc.s.quad ); i++ ) + for ( int i = ARRAY_LENGTH( m_vdc.s.quad ) - 1; i >= 0; i-- ) { int y = m_vdc.s.quad[i].single[0].y & 0xFE; - int height = 8; + + // Character height is always determined by the height of the 4th character + int height = 8 - ( ( ( y >> 1 ) + m_vdc.s.quad[i].single[3].ptr ) & 7 ); + if (height == 1) height = 8; if ( y <= scanline && scanline < y + height * 2 ) { int x = m_vdc.s.quad[i].single[0].x; - // Character height is always determined by the height of the 4th character - int char_height = 8 - ( ( ( y >> 1 ) + m_vdc.s.quad[i].single[3].ptr ) & 7 ); - for ( int j = 0; j < ARRAY_LENGTH( m_vdc.s.quad[0].single ); j++, x += 8 ) { - if ( y <= scanline && scanline < y + char_height * 2 ) - { - uint16_t color = 8 + bgr2rgb[ ( ( m_vdc.s.quad[i].single[j].color >> 1 ) & 0x07 ) ]; - int offset = ( m_vdc.s.quad[i].single[j].ptr | ( ( m_vdc.s.quad[i].single[j].color & 0x01 ) << 8 ) ) + ( y >> 1 ) + ( ( scanline - y ) >> 1 ); - uint8_t chr = m_charset[ offset & 0x1FF ]; + uint16_t color = 8 + bgr2rgb[ ( ( m_vdc.s.quad[i].single[j].color >> 1 ) & 0x07 ) ]; + int offset = ( m_vdc.s.quad[i].single[j].ptr | ( ( m_vdc.s.quad[i].single[j].color & 0x01 ) << 8 ) ) + ( y >> 1 ) + ( ( scanline - y ) >> 1 ); + uint8_t chr = m_charset[ offset & 0x1FF ]; - for ( uint8_t m = 0x80; m > 0; m >>= 1, x++ ) + for ( uint8_t m = 0x80; m > 0; m >>= 1, x++ ) + { + if ( chr & m ) { - if ( chr & m ) + if ( x >= 0 && x < 160 ) { - if ( x >= 0 && x < 160 ) + /* Check if we collide with an already drawn source object */ + if ( collision_map[ x ] & m_vdc.s.collision ) { - /* Check if we collide with an already drawn source object */ - if ( collision_map[ x ] & m_vdc.s.collision ) - { - m_collision_status |= COLLISION_CHARACTERS; - } - /* Check if an already drawn object would collide with us */ - if ( COLLISION_CHARACTERS & m_vdc.s.collision && collision_map[ x ] ) - { - m_collision_status |= collision_map[ x ]; - } - collision_map[ x ] |= COLLISION_CHARACTERS; - m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * x ) = color; - m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * x + 1 ) = color; + m_collision_status |= COLLISION_CHARACTERS; } + /* Check if an already drawn object would collide with us */ + if ( COLLISION_CHARACTERS & m_vdc.s.collision && collision_map[ x ] ) + { + m_collision_status |= collision_map[ x ]; + } + collision_map[ x ] |= COLLISION_CHARACTERS; + m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * x ) = color; + m_tmp_bitmap.pix16( vpos, START_ACTIVE_SCAN + 10 + 2 * x + 1 ) = color; } } } - else - { - x += 8; - } } } } /* Sprites */ - for ( int i = 0; i < ARRAY_LENGTH( m_vdc.s.sprites ); i++ ) + for ( int i = ARRAY_LENGTH( m_vdc.s.sprites ) - 1; i >= 0; i-- ) { int y = m_vdc.s.sprites[i].y; int height = 8; diff --git a/src/mame/drivers/odyssey2.cpp b/src/mame/drivers/odyssey2.cpp index f2a3ae2aefb..a937ac5f5ee 100644 --- a/src/mame/drivers/odyssey2.cpp +++ b/src/mame/drivers/odyssey2.cpp @@ -5,15 +5,12 @@ Driver file to handle emulation of the Odyssey2. TODO: -- odyssey3 cpu/video should have different clocks +- odyssey3 cpu/video should probably have a different XTAL - backgamm does not work, it only shows the background graphics -- chess is missing some graphics: half of the statusbar chars at the top, - and the A-H row at the bottom -- missing questionmark graphics in turtles - homecomp does not work, needs new slot device - g7400 EF9341 R/W is connected to CPU A2, what happens if it is disobeyed? - a lot more issues, probably, this TODO list was written by someone with - no knowledge on odyssey2 + not much knowledge on odyssey2 ***************************************************************************/ @@ -48,12 +45,9 @@ public: void videopac(machine_config &config); void videopacf(machine_config &config); - void init_odyssey2(); - uint32_t screen_update_odyssey2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); protected: - required_device m_maincpu; required_device m_i8244; required_device m_cart; @@ -63,7 +57,6 @@ protected: uint8_t m_p2; uint8_t m_lum; - DECLARE_READ_LINE_MEMBER(t1_read); void odyssey2_palette(palette_device &palette) const; @@ -294,18 +287,11 @@ void g7400_state::g7400_palette(palette_device &palette) const palette.set_pen_colors(0, g7400_colors); } -void odyssey2_state::init_odyssey2() -{ - memset(m_ram, 0, 0x80); - - uint8_t *gfx = memregion("gfx1")->base(); - for (int i = 0; i < 256; i++) - gfx[i] = i; /* TODO: Why i and not 0? */ -} - void odyssey2_state::machine_start() { + memset(m_ram, 0, 0x80); + save_item(NAME(m_ram)); save_item(NAME(m_p1)); save_item(NAME(m_p2)); @@ -605,51 +591,6 @@ void g7400_state::i8243_p7_w(uint8_t data) } -static const gfx_layout odyssey2_graphicslayout = -{ - 8,1, - 256, /* 256 characters */ - 1, /* 1 bits per pixel */ - { 0 }, /* no bitplanes; 1 bit per pixel */ - /* x offsets */ - { - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - }, - /* y offsets */ - { 0 }, - 1*8 -}; - - -static const gfx_layout odyssey2_spritelayout = -{ - 8,1, - 256, /* 256 characters */ - 1, /* 1 bits per pixel */ - { 0 }, /* no bitplanes; 1 bit per pixel */ - /* x offsets */ - { - 7,6,5,4,3,2,1,0 - }, - /* y offsets */ - { 0 }, - 1*8 -}; - - -static GFXDECODE_START( gfx_odyssey2 ) - GFXDECODE_ENTRY( "gfx1", 0x0000, odyssey2_graphicslayout, 0, 2 ) - GFXDECODE_ENTRY( "gfx1", 0x0000, odyssey2_spritelayout, 0, 2 ) -GFXDECODE_END - - void odyssey2_state::odyssey2(machine_config &config) { @@ -671,7 +612,6 @@ void odyssey2_state::odyssey2(machine_config &config) screen.set_screen_update(FUNC(odyssey2_state::screen_update_odyssey2)); screen.set_palette("palette"); - GFXDECODE(config, "gfxdecode", "palette", gfx_odyssey2); PALETTE(config, "palette", FUNC(odyssey2_state::odyssey2_palette), 16); SPEAKER(config, "mono").front_center(); @@ -732,7 +672,6 @@ void g7400_state::g7400(machine_config &config) screen.set_screen_update(FUNC(odyssey2_state::screen_update_odyssey2)); screen.set_palette("palette"); - GFXDECODE(config, "gfxdecode", "palette", gfx_odyssey2); PALETTE(config, "palette", FUNC(g7400_state::g7400_palette), 16); I8243(config, m_i8243); @@ -772,46 +711,40 @@ void g7400_state::odyssey3(machine_config &config) ROM_START (odyssey2) ROM_REGION(0x0400,"maincpu",0) ROM_LOAD ("o2bios.rom", 0x0000, 0x0400, CRC(8016a315) SHA1(b2e1955d957a475de2411770452eff4ea19f4cee)) - ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF) ROM_END ROM_START (videopac) ROM_REGION(0x0400,"maincpu",0) ROM_LOAD ("o2bios.rom", 0x0000, 0x0400, CRC(8016a315) SHA1(b2e1955d957a475de2411770452eff4ea19f4cee)) - ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF) ROM_END ROM_START (videopacf) ROM_REGION(0x0400,"maincpu",0) ROM_LOAD ("c52.rom", 0x0000, 0x0400, CRC(a318e8d6) SHA1(a6120aed50831c9c0d95dbdf707820f601d9452e)) - ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF) ROM_END ROM_START (g7400) ROM_REGION(0x0400,"maincpu",0) ROM_LOAD ("g7400.bin", 0x0000, 0x0400, CRC(e20a9f41) SHA1(5130243429b40b01a14e1304d0394b8459a6fbae)) - ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF) ROM_END ROM_START (jopac) ROM_REGION(0x0400,"maincpu",0) ROM_LOAD ("jopac.bin", 0x0000, 0x0400, CRC(11647ca5) SHA1(54b8d2c1317628de51a85fc1c424423a986775e4)) - ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF) ROM_END ROM_START (odyssey3) ROM_REGION(0x0400, "maincpu", 0) ROM_LOAD ("odyssey3.bin", 0x0000, 0x0400, CRC(e2b23324) SHA1(0a38c5f2cea929d2fe0a23e5e1a60de9155815dc)) - ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF) ROM_END -/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS */ -COMP( 1978, odyssey2, 0, 0, odyssey2, odyssey2, odyssey2_state, init_odyssey2, "Magnavox", "Odyssey 2 (US)", 0 ) -COMP( 1979, videopac, odyssey2, 0, videopac, odyssey2, odyssey2_state, init_odyssey2, "Philips", "Videopac G7000 (Europe)", 0 ) -COMP( 1979, videopacf, odyssey2, 0, videopacf, odyssey2, odyssey2_state, init_odyssey2, "Philips", "Videopac C52 (France)", 0 ) +/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS */ +COMP( 1978, odyssey2, 0, 0, odyssey2, odyssey2, odyssey2_state, empty_init, "Magnavox", "Odyssey 2 (US)", 0 ) +COMP( 1979, videopac, odyssey2, 0, videopac, odyssey2, odyssey2_state, empty_init, "Philips", "Videopac G7000 (Europe)", 0 ) +COMP( 1979, videopacf, odyssey2, 0, videopacf, odyssey2, odyssey2_state, empty_init, "Philips", "Videopac C52 (France)", 0 ) -COMP( 1983, g7400, 0, 0, g7400, odyssey2, g7400_state, init_odyssey2, "Philips", "Videopac Plus G7400 (Europe)", MACHINE_IMPERFECT_GRAPHICS ) -COMP( 1983, jopac, g7400, 0, g7400, odyssey2, g7400_state, init_odyssey2, "Philips (Brandt license)", "Jopac JO7400 (France)", MACHINE_IMPERFECT_GRAPHICS ) -COMP( 1983, odyssey3, g7400, 0, odyssey3, odyssey2, g7400_state, init_odyssey2, "Magnavox", "Odyssey 3 Command Center (US, prototype)", MACHINE_IMPERFECT_GRAPHICS ) +COMP( 1983, g7400, 0, 0, g7400, odyssey2, g7400_state, empty_init, "Philips", "Videopac Plus G7400 (Europe)", MACHINE_IMPERFECT_GRAPHICS ) +COMP( 1983, jopac, g7400, 0, g7400, odyssey2, g7400_state, empty_init, "Philips (Brandt license)", "Jopac JO7400 (France)", MACHINE_IMPERFECT_GRAPHICS ) +COMP( 1983, odyssey3, g7400, 0, odyssey3, odyssey2, g7400_state, empty_init, "Magnavox", "Odyssey 3 Command Center (US, prototype)", MACHINE_IMPERFECT_GRAPHICS )