@@ -164,7 +164,7 @@ class popobear_state : public driver_device
164164 int m_tilemap_base[4 ]{}; // configuration. TODO: shouldn't be needed
165165 std::vector<u16 > m_vram_rearranged;
166166
167- tilemap_t *m_bg_tilemap[4 ]{};
167+ tilemap_t *m_bg_tilemap[4 ][ 2 ] {};
168168
169169 u8 m_irq_enable = 0 ;
170170 u8 m_dsw_select = 0 ;
@@ -176,6 +176,9 @@ class popobear_state : public driver_device
176176
177177 template <u8 Number> TILE_GET_INFO_MEMBER (get_tile_info);
178178
179+ u8 get_tilemap_size (int which);
180+ u8 get_tilemap_enable (int which);
181+ void mark_tilemaps_dirty ();
179182 int tilemap_base_words (u8 number) const ;
180183
181184 void irq_ack_w (u8 data);
@@ -189,6 +192,7 @@ class popobear_state : public driver_device
189192 u8 idchip_r ();
190193 void idchip_w (u8 data);
191194
195+ void draw_tilemap (screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int which, int basereg, int hireg, int xreg);
192196 u32 screen_update (screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
193197 void draw_sprites (bitmap_ind16 &bitmap, const rectangle &cliprect);
194198
@@ -200,6 +204,13 @@ class popobear_state : public driver_device
200204 void magkengo_main_map (address_map &map) ATTR_COLD;
201205};
202206
207+ void popobear_state::mark_tilemaps_dirty ()
208+ {
209+ // unfortunately tilemaps and tilegfx share the same RAM so we're always dirty if we write to RAM
210+ for (int i = 0 ; i < 2 ; i++)
211+ for (int j = 0 ; j < 4 ; j++)
212+ m_bg_tilemap[j][i]->mark_all_dirty ();
213+ }
203214
204215void popobear_state::vram_w (offs_t offset, u16 data, u16 mem_mask)
205216{
@@ -217,11 +228,7 @@ void popobear_state::vram_w(offs_t offset, u16 data, u16 mem_mask)
217228 COMBINE_DATA (&m_vram_rearranged[swapped_offset]);
218229 m_gfxdecode->gfx (0 )->mark_dirty ((swapped_offset) / 32 );
219230
220- // unfortunately tilemaps and tilegfx share the same RAM so we're always dirty if we write to RAM
221- m_bg_tilemap[0 ]->mark_all_dirty ();
222- m_bg_tilemap[1 ]->mark_all_dirty ();
223- m_bg_tilemap[2 ]->mark_all_dirty ();
224- m_bg_tilemap[3 ]->mark_all_dirty ();
231+ mark_tilemaps_dirty ();
225232}
226233
227234static const gfx_layout char_layout =
@@ -263,15 +270,23 @@ void popobear_state::video_start()
263270
264271 m_gfxdecode->gfx (0 )->set_source (reinterpret_cast <u8 *>(&m_vram_rearranged[0 ]));
265272
266- m_bg_tilemap[0 ] = &machine ().tilemap ().create (*m_gfxdecode, tilemap_get_info_delegate (*this , FUNC (popobear_state::get_tile_info<0 >)), TILEMAP_SCAN_ROWS , 8 , 8 , 128 , 64 );
267- m_bg_tilemap[1 ] = &machine ().tilemap ().create (*m_gfxdecode, tilemap_get_info_delegate (*this , FUNC (popobear_state::get_tile_info<1 >)), TILEMAP_SCAN_ROWS , 8 , 8 , 128 , 64 );
268- m_bg_tilemap[2 ] = &machine ().tilemap ().create (*m_gfxdecode, tilemap_get_info_delegate (*this , FUNC (popobear_state::get_tile_info<2 >)), TILEMAP_SCAN_ROWS , 8 , 8 , 128 , 64 );
269- m_bg_tilemap[3 ] = &machine ().tilemap ().create (*m_gfxdecode, tilemap_get_info_delegate (*this , FUNC (popobear_state::get_tile_info<3 >)), TILEMAP_SCAN_ROWS , 8 , 8 , 128 , 64 );
273+ // full height (drawn when enable bits are 0x0d / 0x1d / 0x1f?)
274+ m_bg_tilemap[0 ][0 ] = &machine ().tilemap ().create (*m_gfxdecode, tilemap_get_info_delegate (*this , FUNC (popobear_state::get_tile_info<0 >)), TILEMAP_SCAN_ROWS , 8 , 8 , 128 , 64 );
275+ m_bg_tilemap[1 ][0 ] = &machine ().tilemap ().create (*m_gfxdecode, tilemap_get_info_delegate (*this , FUNC (popobear_state::get_tile_info<1 >)), TILEMAP_SCAN_ROWS , 8 , 8 , 128 , 64 );
276+ m_bg_tilemap[2 ][0 ] = &machine ().tilemap ().create (*m_gfxdecode, tilemap_get_info_delegate (*this , FUNC (popobear_state::get_tile_info<2 >)), TILEMAP_SCAN_ROWS , 8 , 8 , 128 , 64 );
277+ m_bg_tilemap[3 ][0 ] = &machine ().tilemap ().create (*m_gfxdecode, tilemap_get_info_delegate (*this , FUNC (popobear_state::get_tile_info<3 >)), TILEMAP_SCAN_ROWS , 8 , 8 , 128 , 64 );
278+
279+ // half height (drawn when enable bits are 0x05)
280+ m_bg_tilemap[0 ][1 ] = &machine ().tilemap ().create (*m_gfxdecode, tilemap_get_info_delegate (*this , FUNC (popobear_state::get_tile_info<0 >)), TILEMAP_SCAN_ROWS , 8 , 8 , 128 , 32 );
281+ m_bg_tilemap[1 ][1 ] = &machine ().tilemap ().create (*m_gfxdecode, tilemap_get_info_delegate (*this , FUNC (popobear_state::get_tile_info<1 >)), TILEMAP_SCAN_ROWS , 8 , 8 , 128 , 32 );
282+ m_bg_tilemap[2 ][1 ] = &machine ().tilemap ().create (*m_gfxdecode, tilemap_get_info_delegate (*this , FUNC (popobear_state::get_tile_info<2 >)), TILEMAP_SCAN_ROWS , 8 , 8 , 128 , 32 );
283+ m_bg_tilemap[3 ][1 ] = &machine ().tilemap ().create (*m_gfxdecode, tilemap_get_info_delegate (*this , FUNC (popobear_state::get_tile_info<3 >)), TILEMAP_SCAN_ROWS , 8 , 8 , 128 , 32 );
270284
271- m_bg_tilemap[0 ]->set_transparent_pen (0 );
272- m_bg_tilemap[1 ]->set_transparent_pen (0 );
273- m_bg_tilemap[2 ]->set_transparent_pen (0 );
274- m_bg_tilemap[3 ]->set_transparent_pen (0 );
285+ for (int i = 0 ; i < 2 ; i++)
286+ for (int j = 0 ; j < 4 ; j++)
287+ m_bg_tilemap[j][i]->set_transparent_pen (0 );
288+
289+ save_item (NAME (m_vram_rearranged));
275290}
276291
277292
@@ -288,7 +303,7 @@ void popobear_state::video_start()
288303 */
289304void popobear_state::draw_sprites (bitmap_ind16 &bitmap, const rectangle &cliprect)
290305{
291- u8 * vram = reinterpret_cast <u8 *>(m_spriteram.target ());
306+ u8 * vram = reinterpret_cast <u8 *>(m_spriteram.target ());
292307
293308 for (int drawpri = 0xf ; drawpri >= 0x0 ; drawpri--)
294309 {
@@ -380,21 +395,9 @@ void popobear_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprec
380395 }
381396}
382397
383- u32 popobear_state::screen_update (screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect )
398+ u8 popobear_state::get_tilemap_enable ( int which )
384399{
385- bitmap.fill (0 , cliprect);
386-
387400 u16 const *const vreg = m_vregs;
388- // popmessage("%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x",vreg[0x00],vreg[0x01],vreg[0x02],vreg[0x03],vreg[0x04],vreg[0x05],vreg[0x06], vreg[0x07],vreg[0x08],vreg[0x09],vreg[0x0a],vreg[0x0b],m_vregs[0x0c],m_vregs[0x0d],vreg[0x0e],vreg[0x0f]);
389-
390- // vreg[0x00] also looks like it could be some enable registers
391- // 0x82ff - BMC logo
392- // 0x8aff - some attract scenes (no sprites)
393- // 0x8bff - game attract scenes etc. (sprites)
394-
395- // vreg[0x01] is always
396- // 0xfefb
397-
398401 // Per-layer enable byte; a layer draws when non-zero. Value 0x1f selects the
399402 // per-line (line-scroll) mode on the upper two layers; every other non-zero
400403 // value is a plain layer.
@@ -405,10 +408,90 @@ u32 popobear_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, c
405408 (vreg[0x0d ] & 0x00ff ) // layer 3
406409 };
407410
411+ return enable[which];
412+ }
413+
414+ u8 popobear_state::get_tilemap_size (int which)
415+ {
416+ u8 enable = get_tilemap_enable (which);
417+
418+ // 0x0d / 0x1d / 0x1f = larger tilemap
419+ // 0x05 = smaller tilemap
420+
421+ if (enable & 0x08 )
422+ return 0 ;
423+ else
424+ return 1 ;
425+ }
426+
427+
428+ void popobear_state::draw_tilemap (screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int which, int basereg, int hireg, int xreg)
429+ {
430+ int size = get_tilemap_size (which);
431+ rectangle clip = cliprect;
432+ if (get_tilemap_enable (which) & 0x02 ) // or & 0x10 (no, based on popobear ending)
433+ {
434+ int const base = m_vregs[basereg] << 9 , hi = m_vregs[hireg] << 9 ;
435+ for (int line = cliprect.min_y ; line <= cliprect.max_y ; line++)
436+ {
437+ u16 const v = m_vram[base / 2 + line];
438+ u16 u;
439+ if (which & 1 )
440+ u = (m_vram[hi / 2 + line] & 0xff00 ) >> 8 ;
441+ else
442+ u = (m_vram[hi / 2 + line] & 0x00ff );
443+
444+ clip.sety (line, line);
445+ m_bg_tilemap[which][size]->set_scrollx (0 , (v & 0x00ff ) | (u << 8 ));
446+ m_bg_tilemap[which][size]->set_scrolly (0 , ((v & 0xff00 ) >> 8 ) - line);
447+ m_bg_tilemap[which][size]->draw (screen, bitmap, clip, 0 , 0 );
448+ }
449+ }
450+ else if (get_tilemap_enable (which))
451+ {
452+ m_bg_tilemap[which][size]->set_scrollx (0 , m_vregs[xreg]);
453+ m_bg_tilemap[which][size]->set_scrolly (0 , m_vregs[basereg] & 0x1ff );
454+
455+ m_bg_tilemap[which][size]->draw (screen, bitmap, cliprect, 0 , 0 );
456+ }
457+ }
458+
459+
460+ u32 popobear_state::screen_update (screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
461+ {
462+ bitmap.fill (0 , cliprect);
463+ // popmessage("%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x",vreg[0x00],vreg[0x01],vreg[0x02],vreg[0x03],vreg[0x04],vreg[0x05],vreg[0x06], vreg[0x07],vreg[0x08],vreg[0x09],vreg[0x0a],vreg[0x0b],m_vregs[0x0c],m_vregs[0x0d],vreg[0x0e],vreg[0x0f]);
464+
465+ // vreg[0x00] also looks like it could be some enable registers
466+ // 0x82ff - BMC logo
467+ // 0x8aff - some attract scenes (no sprites)
468+ // 0x8bff - game attract scenes etc. (sprites)
469+
470+ // vreg[0x01] is always
471+ // 0xfefb
472+
473+ // regs
474+ // 0 see above
475+ // 1
476+ // 2 tilemap 0 xscroll
477+ // 3 tilemap 0 yscroll
478+ // 4 tilemap 1 xscroll
479+ // 5 tilemap 1 yscroll
480+ // 6 tilemap 0/1 high base
481+ // 7 tilemap 2 xscroll
482+ // 8 tilemap 2 yscroll
483+ // 9 tilemap 3 xscroll
484+ // a tilemap 3 yscroll
485+ // b tilemap 2/3 high base
486+ // c enable 0/1
487+ // d enable 2/3
488+ // e
489+ // f
490+
408491 // pixram
409- if (!enable[ 0 ] && !enable[ 1 ] && !enable[ 2 ] && !enable[ 3 ] && BIT (vreg [0x0e ], 5 ))
492+ if (!get_tilemap_enable ( 0 ) && !get_tilemap_enable ( 1 ) && !get_tilemap_enable ( 2 ) && !get_tilemap_enable ( 3 ) && BIT (m_vregs [0x0e ], 5 ))
410493 {
411- u8 const *const fb = reinterpret_cast <u8 const *>(m_vram.target ()) + ((vreg [0x0e ] & 0x0f ) << 16 );
494+ u8 const *const fb = reinterpret_cast <u8 const *>(m_vram.target ()) + ((m_vregs [0x0e ] & 0x0f ) << 16 );
412495 for (int y = cliprect.min_y ; y <= cliprect.max_y ; y++)
413496 for (int x = cliprect.min_x ; x <= cliprect.max_x ; x++)
414497 {
@@ -420,64 +503,20 @@ u32 popobear_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, c
420503
421504 // Tile RAM and tile gfx share VRAM and the per-layer base can move at runtime,
422505 // so revalidate every frame (vram_w already marks dirty on write).
423- for (auto &tm : m_bg_tilemap)
424- tm->mark_all_dirty ();
425-
426- // Lower two layers: whole-layer scroll.
427- m_bg_tilemap[2 ]->set_scrollx (0 , vreg[0x07 ]);
428- m_bg_tilemap[2 ]->set_scrolly (0 , vreg[0x08 ]);
429- m_bg_tilemap[3 ]->set_scrollx (0 , vreg[0x09 ]);
430- m_bg_tilemap[3 ]->set_scrolly (0 , vreg[0x0a ]);
431- if (enable[3 ]) m_bg_tilemap[3 ]->draw (screen, bitmap, cliprect, 0 , 0 );
432- if (enable[2 ]) m_bg_tilemap[2 ]->draw (screen, bitmap, cliprect, 0 , 0 );
433-
434- // Upper two layers: line-scroll only in mode 0x1f (popobear). The line
435- // tables live in VRAM at (scroll-pointer register << 9): layer0 = vreg[3],
436- // layer1 = vreg[5], shared high-byte table = vreg[6] (e.g. 0x06fa -> 0xdf400).
506+ mark_tilemaps_dirty ();
507+
508+ // line-scroll only in mode 0x1f (popobear). The line
509+ // tables live in VRAM at (scroll-pointer register << 9): layer0 = m_vregs[3],
510+ // layer1 = m_vregs[5], shared high-byte table = m_vregs[6] (e.g. 0x06fa -> 0xdf400).
437511 // Any other non-zero enable is a plain layer (magkengo uses 0x05/0x0d/0x1d).
438- rectangle clip = cliprect;
439512
440- if (enable[1 ] == 0x1f )
441- {
442- int const base = vreg[0x05 ] << 9 , hi = vreg[0x06 ] << 9 ;
443- for (int line = cliprect.min_y ; line <= cliprect.max_y ; line++)
444- {
445- u16 const v = m_vram[base / 2 + line];
446- u16 const u = (m_vram[hi / 2 + line] & 0xff00 ) >> 8 ;
447- clip.sety (line, line);
448- m_bg_tilemap[1 ]->set_scrollx (0 , (v & 0x00ff ) | (u << 8 ));
449- m_bg_tilemap[1 ]->set_scrolly (0 , ((v & 0xff00 ) >> 8 ) - line);
450- m_bg_tilemap[1 ]->draw (screen, bitmap, clip, 0 , 0 );
451- }
452- }
453- else if (enable[1 ])
454- {
455- m_bg_tilemap[1 ]->set_scrollx (0 , 0 );
456- m_bg_tilemap[1 ]->set_scrolly (0 , 0 );
457- m_bg_tilemap[1 ]->draw (screen, bitmap, cliprect, 0 , 0 );
458- }
513+ draw_tilemap (screen, bitmap, cliprect, 3 , 0xa , 0xb , 0x9 );
514+ draw_tilemap (screen, bitmap, cliprect, 2 , 0x8 , 0xb , 0x7 );
459515
460- if (enable[0 ] == 0x1f )
461- {
462- int const base = vreg[0x03 ] << 9 , hi = vreg[0x06 ] << 9 ;
463- for (int line = cliprect.min_y ; line <= cliprect.max_y ; line++)
464- {
465- u16 const v = m_vram[base / 2 + line];
466- u16 const u = (m_vram[hi / 2 + line] & 0x00ff );
467- clip.sety (line, line);
468- m_bg_tilemap[0 ]->set_scrollx (0 , (v & 0x00ff ) | (u << 8 ));
469- m_bg_tilemap[0 ]->set_scrolly (0 , ((v & 0xff00 ) >> 8 ) - line);
470- m_bg_tilemap[0 ]->draw (screen, bitmap, clip, 0 , 0 );
471- }
472- }
473- else if (enable[0 ])
474- {
475- m_bg_tilemap[0 ]->set_scrollx (0 , 0 );
476- m_bg_tilemap[0 ]->set_scrolly (0 , 0 );
477- m_bg_tilemap[0 ]->draw (screen, bitmap, cliprect, 0 , 0 );
478- }
516+ draw_tilemap (screen, bitmap, cliprect, 1 , 0x5 , 0x6 , 0x4 );
517+ draw_tilemap (screen, bitmap, cliprect, 0 , 0x3 , 0x6 , 0x2 );
479518
480- if (BIT (vreg [0x00 ], 8 ))
519+ if (BIT (m_vregs [0x00 ], 8 ))
481520 draw_sprites (bitmap, cliprect);
482521
483522 return 0 ;
@@ -503,7 +542,6 @@ u8 popobear_state::_620000_r()
503542
504543void popobear_state::machine_start ()
505544{
506- save_item (NAME (m_vram_rearranged));
507545 save_item (NAME (m_dsw_select));
508546 save_item (NAME (m_irq_enable));
509547
0 commit comments