1 // license:BSD-3-Clause
2 // copyright-holders:Angelo Salese, David Haywood
3 /*******************************************************************************************
4
5 Popo Bear (c) 2000 BMC
6
7 driver by Angelo Salese, David Haywood
8
9 TODO:
10 - auto-animation speed is erratic (way too fast);
11 - BGM seems quite off, YM2413 core bug?
12 - IRQ generation;
13 - all possible related to some timers?
14
15
16 - I/Os;
17 - Port 0x620000 is quite a mystery, some silly protection?
18
19 ============================================================================================
20 Popo Bear - BMC-A00211
21 (c) 2000 - Bao Ma Technology Co., LTD
22
23 |-----------------------------------------|
24 | DIP2 DIP4 UM3567(YM2413) |J
25 | DIP1 DIP3 |A
26 | TA-A-901 |M
27 | EN-A-701 EN-A-801 U6295(OKI) |M
28 | EN-A-501 EN-A-601 |A
29 | EN-A-301 EN-A-401 |
30 | |C
31 | AIA90610 |O
32 | BMC-68pin AIA90423 |N
33 | plcc (68k) BMC-160pin |N
34 | |E
35 | OSC |C
36 | 42.000 |T
37 |-----------------------------------------|
38
39 1 - BMC AIA90423 - 160-Pin ASIC, FGPA, Video?
40 1 - BMC AIA90610 - 68 Pin CPU (Likely 16 MHz, 68-lead plastic LCC 68000)
41 1 - UM3567 (YM2413) Sound
42 1 - U6295 (OKI6295) Sound
43 1 - 42.000MHz XTAL
44 4 - 8 Position DIP switches
45
46 JAMMA CONNECTOR
47 Component Side A B Solder Side
48 GND 1 1 GND
49 GND 2 2 GND
50 +5v 3 3 +5v
51 +5v 4 4 +5v
52 5 5
53 +12v 6 6 +12v
54 7 7
55 Coin Meter 8 8
56 9 9
57 Speaker 10 10 GND
58 11 11
59 Red 12 12 Green
60 Blue 13 13 Syn
61 GND 14 14
62 Test 15 15
63 Coin1 16 16 Coin2
64 1P Start 17 17 2P Start
65 1P Up 18 18 2P Up
66 1P Down 19 19 2P Down
67 1P Left 20 20 2P Left
68 1P Right 21 21 2P Right
69 1P A 22 22 2P A
70 1P B 23 23 2P B
71 1P C 24 24 2P C
72 25 25
73 26 26
74 GND 27 27 GND
75 GND 28 28 GND
76 *******************************************************************************************/
77
78
79
80 #include "emu.h"
81 #include "cpu/m68000/m68000.h"
82 #include "machine/timer.h"
83 #include "sound/okim6295.h"
84 #include "sound/ym2413.h"
85 #include "emupal.h"
86 #include "screen.h"
87 #include "speaker.h"
88 #include "tilemap.h"
89
90 class popobear_state : public driver_device
91 {
92 public:
popobear_state(const machine_config & mconfig,device_type type,const char * tag)93 popobear_state(const machine_config &mconfig, device_type type, const char *tag) :
94 driver_device(mconfig, type, tag),
95 m_maincpu(*this,"maincpu"),
96 m_gfxdecode(*this, "gfxdecode"),
97 m_palette(*this, "palette"),
98 m_spr(*this, "spr"),
99 m_vram(*this, "vram"),
100 m_vregs(*this, "vregs")
101 {
102 m_tilemap_base[0] = 0xf0000;
103 m_tilemap_base[1] = 0xf4000;
104 m_tilemap_base[2] = 0xf8000;
105 m_tilemap_base[3] = 0xfc000;
106 }
107
108 void popobear(machine_config &config);
109
110 private:
111 required_device<cpu_device> m_maincpu;
112 required_device<gfxdecode_device> m_gfxdecode;
113 required_device<palette_device> m_palette;
114
115 required_shared_ptr<uint16_t> m_spr;
116 required_shared_ptr<uint16_t> m_vram;
117 required_shared_ptr<uint16_t> m_vregs;
118
119 std::vector<uint16_t> m_vram_rearranged;
120 int m_tilemap_base[4];
121 tilemap_t *m_bg_tilemap[4];
122
123 TILE_GET_INFO_MEMBER(get_bg0_tile_info);
124 TILE_GET_INFO_MEMBER(get_bg1_tile_info);
125 TILE_GET_INFO_MEMBER(get_bg2_tile_info);
126 TILE_GET_INFO_MEMBER(get_bg3_tile_info);
127
128 uint8_t _620000_r();
129 void irq_ack_w(uint8_t data);
130 void vram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
131
132 virtual void video_start() override;
133 uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
134 void draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect);
135
136 TIMER_DEVICE_CALLBACK_MEMBER(irq);
137
138 void postload();
139 void popobear_mem(address_map &map);
140 };
141
142
vram_w(offs_t offset,uint16_t data,uint16_t mem_mask)143 void popobear_state::vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
144 {
145 COMBINE_DATA(&m_vram[offset]);
146
147 // the graphic data for the tiles is in a strange order, rearrange it so that we can use it as tiles..
148 int swapped_offset = bitswap<32>(offset, /* unused bits */ 31,30,29,28,27,26,25,24,23,22,21,20,19, /* end unused bits */
149
150 18,17,16,15,14,13,12,
151
152 8,7,6,5,4,3,2,
153
154 11,10,9, /* y tile address bits */
155
156 1,0 /* x tile address bits */);
157
158
159
160 COMBINE_DATA(&m_vram_rearranged[swapped_offset]);
161 m_gfxdecode->gfx(0)->mark_dirty((swapped_offset)/32);
162
163 // unfortunately tilemaps and tilegfx share the same ram so we're always dirty if we write to RAM
164 m_bg_tilemap[0]->mark_all_dirty();
165 m_bg_tilemap[1]->mark_all_dirty();
166 m_bg_tilemap[2]->mark_all_dirty();
167 m_bg_tilemap[3]->mark_all_dirty();
168 }
169
170 static const gfx_layout char_layout =
171 {
172 8,8,
173 RGN_FRAC(1,1),
174 8,
175 { 0,1,2,3,4,5,6,7 },
176 { STEP8(0, 8) },
177 { STEP8(0, 64) },
178 8*64
179 };
180
181 GFXDECODE_START(gfx_popobear)
182 GFXDECODE_RAM( "vram", 0, char_layout, 0, 1 )
183 GFXDECODE_END
184
TILE_GET_INFO_MEMBER(popobear_state::get_bg0_tile_info)185 TILE_GET_INFO_MEMBER(popobear_state::get_bg0_tile_info)
186 {
187 int base = m_tilemap_base[0];
188 int tileno = m_vram[base/2 + tile_index];
189 int flipyx = (tileno>>14);
190 tileinfo.set(0, tileno&0x3fff, 0, TILE_FLIPYX(flipyx));
191 }
192
TILE_GET_INFO_MEMBER(popobear_state::get_bg1_tile_info)193 TILE_GET_INFO_MEMBER(popobear_state::get_bg1_tile_info)
194 {
195 int base = m_tilemap_base[1];
196 int tileno = m_vram[base/2 + tile_index];
197 int flipyx = (tileno>>14);
198 tileinfo.set(0, tileno&0x3fff, 0, TILE_FLIPYX(flipyx));
199 }
200
TILE_GET_INFO_MEMBER(popobear_state::get_bg2_tile_info)201 TILE_GET_INFO_MEMBER(popobear_state::get_bg2_tile_info)
202 {
203 int base = m_tilemap_base[2];
204 int tileno = m_vram[base/2 + tile_index];
205 int flipyx = (tileno>>14);
206 tileinfo.set(0, tileno&0x3fff, 0, TILE_FLIPYX(flipyx));
207 }
208
TILE_GET_INFO_MEMBER(popobear_state::get_bg3_tile_info)209 TILE_GET_INFO_MEMBER(popobear_state::get_bg3_tile_info)
210 {
211 int base = m_tilemap_base[3];
212 int tileno = m_vram[base/2 + tile_index];
213 int flipyx = (tileno>>14);
214 tileinfo.set(0, tileno&0x3fff, 0, TILE_FLIPYX(flipyx));
215 }
216
217
postload()218 void popobear_state::postload()
219 {
220 m_gfxdecode->gfx(0)->mark_all_dirty();
221 }
222
video_start()223 void popobear_state::video_start()
224 {
225 m_vram_rearranged.resize(0x100000 / 2);
226
227 m_gfxdecode->gfx(0)->set_source(reinterpret_cast<uint8_t *>(&m_vram_rearranged[0]));
228
229 m_bg_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(popobear_state::get_bg0_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 128, 64);
230 m_bg_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(popobear_state::get_bg1_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 128, 64);
231 m_bg_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(popobear_state::get_bg2_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 128, 64);
232 m_bg_tilemap[3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(popobear_state::get_bg3_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 128, 64);
233
234 m_bg_tilemap[0]->set_transparent_pen(0);
235 m_bg_tilemap[1]->set_transparent_pen(0);
236 m_bg_tilemap[2]->set_transparent_pen(0);
237 m_bg_tilemap[3]->set_transparent_pen(0);
238
239 save_item(NAME(m_vram_rearranged));
240 machine().save().register_postload(save_prepost_delegate(FUNC(popobear_state::postload), this));
241 }
242
243
244
245
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect)246 void popobear_state::draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect)
247 {
248 uint8_t* vram = reinterpret_cast<uint8_t *>(m_spr.target());
249 int i;
250
251 /*
252 ???? ---- ---- ---- unused?
253 ---- xxxx ---- ---- priority (against other sprites! used to keep the line of characters following you in order)
254 ---- ---- x--- ---- Y direction
255 ---- ---- -x-- ---- X direction
256 ---- ---- --xx ---- size (height & width)
257 ---- ---- ---- xx-- color bank
258 ---- ---- ---- --x- NOT set on the enemy character / characters in your line
259 ---- ---- ---- ---x set on opposite to above?
260 */
261
262 for (int drawpri = 0xf;drawpri>=0x0;drawpri--)
263 {
264 /* 0x106 = 8 x 8 */
265 /* 0x*29 = 32 x 32 */
266 for(i = 0x800-8;i >= 0; i-=8)
267 {
268 uint16_t *sprdata = &m_spr[(0x7f800 + i) / 2];
269
270 int param = sprdata[0];
271 int pri = (param & 0x0f00)>>8;
272
273 // we do this because it's sprite<->sprite priority,
274 if (pri!=drawpri)
275 continue;
276
277 int y = sprdata[1];
278 int x = sprdata[2];
279 int spr_num = sprdata[3];
280
281 int width = 8 << ((param & 0x30)>>4);
282 int height = width; // sprites are always square?
283
284 int color_bank = ((param & 0xc)>>2);
285 int x_dir = param & 0x40;
286 int y_dir = param & 0x80;
287
288 if (x&0x8000) x-= 0x10000;
289 if (y&0x8000) y-= 0x10000;
290
291 if (param&0xf000) color_bank = (machine().rand() & 0x3);
292
293
294
295 int add_it = 0;
296
297 // this isn't understood, not enough evidence.
298 switch (param & 3)
299 {
300 case 0x0: // not used?
301 color_bank = (machine().rand() & 0x3);
302 add_it = color_bank*0x40;
303 break;
304
305 case 0x1: // butterflies in intro, enemy characters, line of characters, stage start text
306 //color_bank = (machine().rand() & 0x3);
307 add_it = color_bank*0x40;
308 break;
309
310 case 0x2: // characters in intro, main player, powerups, timer, large dancing chars between levels (0x3f?)
311 //color_bank = (machine().rand() & 0x3);
312 add_it = color_bank*0x40;
313 break;
314
315 case 0x3: // letters on GAME OVER need this..
316 add_it = color_bank*0x40;
317 add_it += 0x20;
318 break;
319 }
320
321 if(param == 0)
322 continue;
323
324
325 spr_num <<= 3;
326
327 for(int yi=0;yi<height;yi++)
328 {
329 int y_draw = (y_dir) ? y+((height-1) - yi) : y+yi;
330
331 for(int xi=0;xi<width;xi++)
332 {
333 uint8_t pix = vram[BYTE_XOR_BE(spr_num)];
334 int x_draw = (x_dir) ? x+((width-1) - xi) : x+xi;
335
336 if(cliprect.contains(x_draw, y_draw))
337 {
338 // this is a bit strange, pix data is basically 8-bit
339 // but we have to treat 0x00, 0x40, 0x80, 0xc0 */
340 // see scores when you colect an item, must be at least steps of 0x40 or one of the female panda gfx between levels breaks.. might depend on lower bits?
341 // granularity also means colour bank is applied *0x40
342 // and we have 2 more possible colour bank bits
343 // colours on game over screen are still wrong without the weird param kludge above
344 if (pix&0x3f)
345 {
346 bitmap.pix(y_draw, x_draw) = m_palette->pen(((pix+(add_it))&0xff)+0x100);
347 }
348 }
349
350 spr_num++;
351 }
352 }
353 }
354 }
355 }
356
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)357 uint32_t popobear_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
358 {
359 bitmap.fill(0, cliprect);
360 int line;
361 rectangle clip;
362 int scrollbase;
363 int scrollbase2;
364
365 const rectangle &visarea = screen.visible_area();
366 clip = visarea;
367
368 //popmessage("%04x",m_vregs[0/2]);
369 uint16_t* vreg = m_vregs;
370
371 // popmessage("%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[0x0b],vreg[0x0e],vreg[0x0f]);
372
373 // vreg[0x00] also looks like it could be some enable registers
374 // 0x82ff - BMC logo
375 // 0x8aff - some attract scenes (no sprites)
376 // 0x8bff - game attract scense etc. (sprites)
377
378 // vreg[0x01] is always
379 // 0xfefb
380
381
382
383 // these are more than just enable, they get written with 0x0d and 0x1f (and 0x00 when a layer is off)
384 // seems to be related to the linescroll mode at least? maybe sizes?
385 int enable0 = (m_vregs[0x0c] & 0xff00)>>8;
386 int enable1 = (m_vregs[0x0c] & 0x00ff)>>0;
387 int enable2 = (m_vregs[0x0d] & 0xff00)>>8;
388 int enable3 = (m_vregs[0x0d] & 0x00ff)>>0;
389
390 if ((enable0 != 0x00) && (enable0 != 0x0d) && (enable0 != 0x1f)) printf("unknown enable0 value %02x\n", enable0);
391 if ((enable1 != 0x00) && (enable1 != 0x0d) && (enable1 != 0x1f)) printf("unknown enable1 value %02x\n", enable1);
392 if ((enable2 != 0x00) && (enable2 != 0x0d)) printf("unknown enable2 value %02x\n", enable2);
393 if ((enable3 != 0x00) && (enable3 != 0x0d)) printf("unknown enable3 value %02x\n", enable3);
394
395
396 // the lower 2 tilemaps use regular scrolling
397 m_bg_tilemap[2]->set_scrollx(0, vreg[0x07]);
398 m_bg_tilemap[2]->set_scrolly(0, vreg[0x08]);
399
400 m_bg_tilemap[3]->set_scrollx(0, vreg[0x09]);
401 m_bg_tilemap[3]->set_scrolly(0, vreg[0x0a]);
402
403 if (enable3) m_bg_tilemap[3]->draw(screen, bitmap, cliprect, 0, 0);
404 if (enable2) m_bg_tilemap[2]->draw(screen, bitmap, cliprect, 0, 0);
405
406 // the upper 2 tilemaps have a lineselect / linescroll logic
407
408 if (enable1 == 0x1f)
409 {
410 scrollbase = 0xdf600;
411 scrollbase2 = 0xdf800;
412
413 for (line = 0; line < 240;line++)
414 {
415 uint16_t val = m_vram[scrollbase/2 + line];
416 uint16_t upper = (m_vram[scrollbase2/2 + line]&0xff00)>>8;
417
418 clip.sety(line, line);
419
420 m_bg_tilemap[1]->set_scrollx(0,(val&0x00ff) | (upper << 8));
421 m_bg_tilemap[1]->set_scrolly(0,((val&0xff00)>>8)-line);
422
423 m_bg_tilemap[1]->draw(screen, bitmap, clip, 0, 0);
424 }
425 }
426 else if (enable1 != 0x00)
427 {
428 m_bg_tilemap[1]->set_scrollx(0, 0);
429 m_bg_tilemap[1]->set_scrolly(0, 0);
430 m_bg_tilemap[1]->draw(screen, bitmap, cliprect, 0, 0);
431 }
432
433 if (enable0 == 0x1f)
434 {
435 scrollbase = 0xdf400;
436 scrollbase2 = 0xdf800;
437
438 for (line = 0; line < 240;line++)
439 {
440 uint16_t val = m_vram[scrollbase/2 + line];
441 uint16_t upper = (m_vram[scrollbase2/2 + line]&0x00ff)>>0;
442
443 clip.sety(line, line);
444
445 m_bg_tilemap[0]->set_scrollx(0,(val&0x00ff) | (upper << 8));
446 m_bg_tilemap[0]->set_scrolly(0,((val&0xff00)>>8)-line);
447
448 m_bg_tilemap[0]->draw(screen, bitmap, clip, 0, 0);
449 }
450 }
451 else if (enable0 != 0x00)
452 {
453 m_bg_tilemap[0]->set_scrollx(0, 0);
454 m_bg_tilemap[0]->set_scrolly(0, 0);
455 m_bg_tilemap[0]->draw(screen, bitmap, cliprect, 0, 0);
456 }
457
458 draw_sprites(bitmap,cliprect);
459
460 return 0;
461 }
462
463 /* ??? */
_620000_r()464 uint8_t popobear_state::_620000_r()
465 {
466 return 9;
467 }
468
irq_ack_w(uint8_t data)469 void popobear_state::irq_ack_w(uint8_t data)
470 {
471 for(int i=0;i<8;i++)
472 {
473 if(data & 1 << i)
474 m_maincpu->set_input_line(i, CLEAR_LINE);
475 }
476 }
477
popobear_mem(address_map & map)478 void popobear_state::popobear_mem(address_map &map)
479 {
480 map.unmap_value_high();
481 map(0x000000, 0x03ffff).rom();
482 map(0x210000, 0x21ffff).ram();
483 map(0x280000, 0x2fffff).ram().share("spr"); // unknown boundaries, 0x2ff800 contains a sprite list, lower area = sprite gfx
484 map(0x300000, 0x3fffff).ram().w(FUNC(popobear_state::vram_w)).share("vram"); // tile definitions + tilemaps
485
486
487 /* Most if not all of these are vregs */
488 map(0x480000, 0x48001f).ram().share("vregs");
489 map(0x480020, 0x480023).ram();
490 map(0x480028, 0x48002d).ram();
491 // map(0x480020, 0x480021).noprw(); //.rw(FUNC(popobear_state::480020_r) FUNC(popobear_state::480020_w));
492 // map(0x480028, 0x480029).noprw(); //.w(FUNC(popobear_state::480028_w));
493 // map(0x48002c, 0x48002d).noprw(); //.w(FUNC(popobear_state::48002c_w));
494 map(0x480031, 0x480031).w(FUNC(popobear_state::irq_ack_w));
495 map(0x480034, 0x480035).ram(); // coin counter or coin lockout
496 map(0x48003a, 0x48003b).ram(); //.rw(FUNC(popobear_state::48003a_r) FUNC(popobear_state::48003a_w));
497
498 map(0x480400, 0x4807ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
499
500 map(0x500000, 0x500001).portr("IN0");
501 map(0x520000, 0x520001).portr("IN1");
502 map(0x540001, 0x540001).rw("oki", FUNC(okim6295_device::read), FUNC(okim6295_device::write));
503 map(0x550000, 0x550003).w("ymsnd", FUNC(ym2413_device::write)).umask16(0x00ff);
504
505 map(0x600000, 0x600001).nopw();
506 map(0x620000, 0x620000).r(FUNC(popobear_state::_620000_r));
507 map(0x620000, 0x620001).nopw();
508 map(0x800000, 0xbfffff).rom();
509 }
510
511 static INPUT_PORTS_START( popobear )
512
513 PORT_START("DSW1")
DEF_STR(Demo_Sounds)514 PORT_DIPNAME( 0x01, 0x01, DEF_STR( Demo_Sounds ) )
515 PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
516 PORT_DIPSETTING( 0x01, DEF_STR( On ) )
517 PORT_DIPNAME( 0x0e, 0x00, "Coin_A" )
518 PORT_DIPSETTING( 0x0c, DEF_STR( 3C_1C ) )
519 PORT_DIPSETTING( 0x0a, DEF_STR( 2C_1C ) )
520 PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ) )
521 PORT_DIPSETTING( 0x02, DEF_STR( 1C_2C ) )
522 PORT_DIPSETTING( 0x04, DEF_STR( 1C_3C ) )
523 PORT_DIPSETTING( 0x06, DEF_STR( 1C_4C ) )
524 PORT_DIPSETTING( 0x08, DEF_STR( 1C_5C ) )
525 PORT_DIPSETTING( 0x0e, "Freeplay" )
526 PORT_DIPNAME( 0x30, 0x00, DEF_STR( Lives ) )
527 PORT_DIPSETTING( 0x10, "2" )
528 PORT_DIPSETTING( 0x00, "3" )
529 PORT_DIPSETTING( 0x20, "4" )
530 PORT_DIPSETTING( 0x30, "5" )
531 PORT_DIPNAME( 0xc0, 0x00, DEF_STR( Difficulty ) )
532 PORT_DIPSETTING( 0x80, DEF_STR( Very_Easy ) )
533 PORT_DIPSETTING( 0x40, DEF_STR( Easy ) )
534 PORT_DIPSETTING( 0x00, DEF_STR( Normal ) )
535 PORT_DIPSETTING( 0xc0, DEF_STR( Hard ) )
536
537 PORT_START("DSW2")
538 PORT_DIPNAME( 0x01, 0x00, "Arrow" )
539 PORT_DIPSETTING( 0x01, DEF_STR( No ) )
540 PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
541 PORT_DIPNAME( 0x02, 0x00, "DSW2:2" )
542 PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
543 PORT_DIPSETTING( 0x02, DEF_STR( On ) )
544 PORT_DIPNAME( 0x04, 0x00, "DSW2:3" )
545 PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
546 PORT_DIPSETTING( 0x04, DEF_STR( On ) )
547 PORT_DIPNAME( 0x08, 0x00, "DSW2:4" )
548 PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
549 PORT_DIPSETTING( 0x08, DEF_STR( On ) )
550 PORT_DIPNAME( 0x10, 0x00, "DSW2:5" )
551 PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
552 PORT_DIPSETTING( 0x10, DEF_STR( On ) )
553 PORT_DIPNAME( 0x20, 0x00, "DSW2:6" )
554 PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
555 PORT_DIPSETTING( 0x20, DEF_STR( On ) )
556 PORT_DIPNAME( 0x40, 0x00, "DSW2:7" )
557 PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
558 PORT_DIPSETTING( 0x40, DEF_STR( On ) )
559 PORT_DIPNAME( 0x80, 0x00, "DSW2:8" )
560 PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
561 PORT_DIPSETTING( 0x80, DEF_STR( On ) )
562
563 PORT_START("IN0")
564 PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
565 PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
566 PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
567 PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
568 PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
569 PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
570 PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
571 PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNUSED )
572 PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1)
573 PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1)
574 PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1)
575 PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1)
576 PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
577 PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
578 PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1)
579 PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNUSED )
580
581 PORT_START("IN1")
582 PORT_DIPNAME( 0x01, 0x01, "DSWA" )
583 PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
584 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
585 PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
586 PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
587 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
588 PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
589 PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
590 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
591 PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
592 PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
593 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
594 PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
595 PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
596 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
597 PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
598 PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
599 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
600 PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
601 PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
602 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
603 PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
604 PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
605 PORT_DIPSETTING( 0x00, DEF_STR( On ) )
606 PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(2)
607 PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) )
608 PORT_DIPSETTING( 0x0200, DEF_STR( Off ) )
609 PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
610 PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) )
611 PORT_DIPSETTING( 0x0400, DEF_STR( Off ) )
612 PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
613 PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) )
614 PORT_DIPSETTING( 0x0800, DEF_STR( Off ) )
615 PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
616 PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) )
617 PORT_DIPSETTING( 0x1000, DEF_STR( Off ) )
618 PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
619 PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) )
620 PORT_DIPSETTING( 0x2000, DEF_STR( Off ) )
621 PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
622 PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_START2 )
623 PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_START1 )
624 INPUT_PORTS_END
625
626
627 TIMER_DEVICE_CALLBACK_MEMBER(popobear_state::irq)
628 {
629 int scanline = param;
630
631 /* Order is trusted (5 as vblank-out makes the title screen logo spinning to behave wrongly) */
632 if(scanline == 240)
633 m_maincpu->set_input_line(3, ASSERT_LINE);
634
635 if(scanline == 0)
636 m_maincpu->set_input_line(5, ASSERT_LINE);
637
638 /* TODO: actually a timer irq, tied with YM2413 sound chip (controls BGM tempo) */
639 /* the YM2413 doesn't have interrupts? */
640 if(scanline == 64 || scanline == 192)
641 m_maincpu->set_input_line(2, ASSERT_LINE);
642 }
643
popobear(machine_config & config)644 void popobear_state::popobear(machine_config &config)
645 {
646 M68000(config, m_maincpu, XTAL(42'000'000)/4); // XTAL CORRECT, DIVISOR GUESSED
647 m_maincpu->set_addrmap(AS_PROGRAM, &popobear_state::popobear_mem);
648 // levels 2,3,5 look interesting
649 //->set_vblank_int("screen", popobear_state, irq5_line_assert)
650 //->set_periodic_int(FUNC(popobear_state, irq2_line_assert, 120)
651 TIMER(config, "scantimer").configure_scanline(FUNC(popobear_state::irq), "screen", 0, 1);
652
653 screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
654 screen.set_refresh_hz(60);
655 screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
656 screen.set_screen_update(FUNC(popobear_state::screen_update));
657 screen.set_palette(m_palette);
658 screen.set_size(128*8, 32*8);
659 screen.set_visarea(0, 479, 0, 239);
660
661 PALETTE(config, m_palette).set_format(palette_device::xBGR_555, 256*2);
662
663 SPEAKER(config, "mono").front_center();
664
665 GFXDECODE(config, m_gfxdecode, m_palette, gfx_popobear);
666
667 YM2413(config, "ymsnd", XTAL(42'000'000)/16).add_route(ALL_OUTPUTS, "mono", 1.0); // XTAL CORRECT, DIVISOR GUESSED
668
669 OKIM6295(config, "oki", XTAL(42'000'000)/32, okim6295_device::PIN7_LOW).add_route(ALL_OUTPUTS, "mono", 1.0); // XTAL CORRECT, DIVISOR GUESSED
670 }
671
672
673 ROM_START( popobear )
674 ROM_REGION( 0x1000000, "maincpu", 0 ) /* 68000 Code + gfx data */
675 ROM_LOAD16_BYTE( "popobear_en-a-301_1.6.u3", 0x000001, 0x020000, CRC(b934adf6) SHA1(93431c7a19af812b549aad35cc1176a81805ffab) )
676 ROM_LOAD16_BYTE( "popobear_en-a-401_1.6.u4", 0x000000, 0x020000, CRC(0568af9c) SHA1(920531dbc4bbde2d1db062bd5c48b97dd50b7185) )
677 ROM_LOAD16_BYTE( "popobear_en-a-501.u5", 0x800001, 0x100000, CRC(185901a9) SHA1(7ff82b5751645df53435eaa66edce589684cc5c7) )
678 ROM_LOAD16_BYTE( "popobear_en-a-601.u6", 0x800000, 0x100000, CRC(84fa9f3f) SHA1(34dd7873f88b0dae5fb81fe84e82d2b6b49f7332) )
679 ROM_LOAD16_BYTE( "popobear_en-a-701.u7", 0xa00001, 0x100000, CRC(45eba6d0) SHA1(0278602ed57ac45040619d590e6cc85e2cfeed31) )
680 ROM_LOAD16_BYTE( "popobear_en-a-801.u8", 0xa00000, 0x100000, CRC(2760f2e6) SHA1(58af59f486c9df930f7c124f89154f8f389a5bd7) )
681
682 ROM_REGION( 0x040000, "oki", 0 ) /* Samples */
683 ROM_LOAD( "popobear_ta-a-901.u9", 0x00000, 0x40000, CRC(f1e94926) SHA1(f4d6f5b5811d90d0069f6efbb44d725ff0d07e1c) )
684 ROM_END
685
686 GAME( 2000, popobear, 0, popobear, popobear, popobear_state, empty_init, ROT0, "BMC", "PoPo Bear", MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
687